DEV Community

Cover image for BoldSign Formula Fields: Automate Calculations in eSignature Documents
Vijay Amalan for BoldSign

Posted on • Originally published at boldsign.com

BoldSign Formula Fields: Automate Calculations in eSignature Documents

Manually calculating values in documents can be time-consuming and leave you prone to error, especially when dealing with contracts, invoices, or agreements that require dynamic values like totals, taxes, or discounts. You might struggle to ensure accuracy and consistency across multiple signers and documents. Repetitive manual entry of calculated fields like subtotals, taxes, and totals increases the risk of human error, which can lead to compliance issues or financial discrepancies. It can also cause delays in document turnaround because calculations need verification before sending.

What if you could automate these calculations directly within your e-signature workflow? That’s where BoldSign formula fields come in.

What problems do formula fields solve in eSignature documents?

With formula fields, you can define dynamic calculations directly in your e-signature documents using the BoldSign API.

Key benefits include:

  • Automated calculations: You can perform real-time calculations like totals, taxes, discounts, or custom formulas based on other field values.
  • Error reduction: Reduce manual entry errors by computing values automatically, ensuring consistency and accuracy.
  • Improved user experience: Signers don’t need to do math themselves. The document updates instantly as they fill in fields.
  • Dynamic content: You can create smart documents that adapt based on user input, making them more interactive and professional.
  • Time savings: Save time for both senders and signers by eliminating the need for manual calculations or post-signing edits.
  • Supports complex logic: Use functions like IF for advanced scenarios.

How do BoldSign formula fields work?

These formulas are built using supported operators, functions, and fields without storing static data. As signers enter values into the form, the formula fields in the document recalculate instantly. This ensures accurate results and reduces manual effort.

Which fields, operators, and functions are supported?

BoldSign formula fields support various form fields, operators, and functions to help you streamline arithmetic calculations in your e-signature documents.

How do you add formula fields to a document API request?

When creating or sending a document or template via the BoldSign API, you can add formula fields programmatically by including them in the formFields array of your request payload.

Here’s what to include:

  • fieldType: Set to “Formula” to indicate it’s a formula field.
  • formulaFieldSettings: This object contains:
    • formulaExpression: The actual calculation logic (e.g., “[textbox1] – [textbox2]”). Use only the field ID in your formula expression.
    • decimalPrecision: The number of decimal places to show in the result.

What does a vehicle sales agreement example look like with formula fields?

Let’s look at a practical example. Suppose you’re sending a vehicle sales agreement and want the signer to enter:

  • Total vehicle value → [Textbox1].
  • Deposit amount → [Textbox2].

From these inputs, you want to:

  • Calculate the remaining balance.

Formula: Balance = [Textbox1]- [Textbox2]

  • Set the Payment Date to be seven days from the signing date.

Formula: PaymentDate = AddDays([SigningDate], 7)

(Payment should be made 7 days from the signing date.)

When the document is sent via the BoldSign API, the balance and payment date are automatically calculated in real time as the signer fills in the values. This eliminates manual math, reduces errors, and improves the signing experience.

Here are example code snippets for sending a signature request with formula fields via API.

cURL

    curl -X 'POST' \
      'https://api.boldsign.com/v1/document/send' \
      -H 'accept: application/json' \
      -H 'X-API-KEY: {your API key}' \
      -H 'Content-Type: application/json' \
      -d '{
        "Signers": [
          {
            "Name": "Hanky",
            "EmailAddress": " david@cubeflakes.com",
            "SignerType": "Signer",
            "DeliveryMode": "Email",
            "FormFields": [
              {
                "Id": "signature1",   
                "FieldType": "Signature",
                "PageNumber": 1,
                "Bounds": { "X": 50, "Y": 50, "Width": 100, "Height": 50 },
                "IsRequired": true
              },
              {
                "Id": "textbox1",              // TextBox 1
                "FieldType": "TextBox",
                "PageNumber": 1,
                "Bounds": { "X": 50, "Y": 100, "Width": 100, "Height": 30 },
                "IsRequired": true,
                "ValidationType": "NumbersOnly"
              },
              {
                "Id": "textbox2",          // TextBox 2
                "FieldType": "TextBox",
                "PageNumber": 1,
                "Bounds": { "X": 200, "Y": 100, "Width": 100, "Height": 30 },
                "IsRequired": true,
                "ValidationType": "NumbersOnly"
              },
              {
                "Id": "SigningDate",        // Signing Date
                "FieldType": "DateSigned",
                "PageNumber": 1,
                "Bounds": { "X": 200, "Y": 200, "Width": 125, "Height": 25 },
                "IsRequired": true
              },
              {
                "Id": "PaymentDate",     # Payment Date (7 days after Signing Date)
                "FieldType": "Formula",
                "PageNumber": 1,
                "Bounds": { "X": 50, "Y": 200, "Width": 200, "Height": 30 },
                "FormulaFieldSettings": {
                  "FormulaExpression": "AddDays([SigningDate],7)",
                }
              },
              {
                "Id": "Balance",   // Balance (Formula)
                "FieldType": "Formula",
                "PageNumber": 1,
                "Bounds": { "X": 50, "Y": 250, "Width": 200, "Height": 30 },
                "FormulaFieldSettings": {
                  "FormulaExpression": "[textbox1] - [textbox2]",
                  "DecimalPrecision": 1
                }
              }
            ],
            "Locale": "EN"
          }
        ],
        "ExpiryDays": 30,
        "Files": [
          "data:application/pdf;base64,JVBERi0xLjcKJcfs..." 
        ],
        "Title": "Vehicle Sales Agreement",
        "ExpiryDateType": "Days",
        "ExpiryValue": 60,
        }
      }'
Enter fullscreen mode Exit fullscreen mode

c#

    var apiClient = new ApiClient("https://api.boldsign.com", "Your API Key");
                    var documentClient = new DocumentClient(apiClient);

                    // Define all form fields
                    List<FormField> formField = new List<FormField>
                    {
                        // Signature field
                        new FormField(
                            id: "Signature",
                            type: FieldType.Signature,
                            pageNumber: 1,
                            bounds: new Rectangle(x: 50, y: 50, width: 200, height: 30)),

                        // TextBox 1
                        new TextBoxField(
                            id: "textbox1",
                            validationType: BoldSign.Model.ValidationType.NumbersOnly,
                            pageNumber: 1,
                            bounds: new Rectangle(x: 50, y: 100, width: 100, height: 30),
                            isRequired: true),

                        // TextBox 2
                        new TextBoxField(
                            id: "textbox2",
                            validationType: BoldSign.Model.ValidationType.NumbersOnly,
                            pageNumber: 1,
                            bounds: new Rectangle(x: 200, y: 100, width: 100, height: 30),
                            isRequired: true),

                        // Signing date
                        new FormField(
                            id: "SigningDate",
                            type: FieldType.DateSigned,
                            pageNumber: 1,
                            bounds: new Rectangle(x: 200, y: 200, width: 125, height: 25),
                            isRequired: true),

                        // Payment date
                        new FormField(
                            id: "PaymentDate",
                            type: FieldType.Formula,
                            pageNumber: 1,
                            bounds: new Rectangle(x: 50, y: 200, width: 200, height: 30),
                            isRequired: true
                            ),

                        // Balance (formula)
                        new FormField(
                            id: "Balance",
                            type: FieldType.Formula,
                            pageNumber: 1,
                            bounds: new Rectangle(x: 50, y: 250, width: 200, height: 30),
                            isRequired: true
                            )
                    };

                    formField[4].FormulaFieldSettings= new FormulaFieldSettings
                    {
                        FormulaExpression = "AddDays([SigningDate],7)",
                    };
                    formField[5].FormulaFieldSettings = new FormulaFieldSettings
                    {
                        FormulaExpression = "[textbox1] - [textbox2]",
                        DecimalPrecision = 1
                    };

                    // Document details
                    var documentDetails = new SendForSign
                    {
                        Title = "Agreement",
                        Signers = new List<DocumentSigner>
                        {
                            new DocumentSigner(
                                signerName: "David",
                                signerType: SignerType.Signer,
                                signerEmail: "david@cubeflakes.com",
                                formFields: formField)
                        },
                        Files = new List<IDocumentFile>
                        {
                            new DocumentFilePath
                            {
                                ContentType = "application/pdf",
                                FilePath = "Your File Path.pdf",
                            }
                        },
                    };

                    // Send document
                    var documentCreated = documentClient.SendDocument(documentDetails);
                    Console.WriteLine($"Document sent successfully. Document ID: {documentCreated?.DocumentId}");
Enter fullscreen mode Exit fullscreen mode

Python

    import boldsign
    configuration = boldsign.Configuration(api_key="Your API Key ")
    with boldsign.ApiClient(configuration) as api_client:
        document_api = boldsign.DocumentApi(api_client)
        # Signature field
        signature_field = boldsign.FormField(
            fieldType="Signature",
            pageNumber=1,
            bounds=boldsign.Rectangle(x=50, y=50, width=200, height=25)
        )
        # Total vehicle value
        textbox1 = boldsign.FormField(
            id="textbox1",
            fieldType="TextBox",
            pageNumber=1,
            bounds=boldsign.Rectangle(x=50, y=100, width=100, height=30),
            validationType="NumbersOnly",
            isRequired=True
        )
        # Deposit amount
        textbox2 = boldsign.FormField(
            id="textbox2",
            fieldType="TextBox",
            pageNumber=1,
            bounds=boldsign.Rectangle(x=200, y=100, width=150, height=30),
            validationType="NumbersOnly",
            isRequired=True
        )
    # Balance formula
    formula_balance = boldsign.FormField(
        id="FormulaBalance",
        fieldType="Formula",
        pageNumber=1,
        bounds=boldsign.Rectangle(x=50, y=150, width=200, height=30),
        formulaFieldSettings=boldsign.FormulaFieldSettings(
            formulaExpression="[textbox1] - [textbox2]", 
            decimalPrecision=1
        )
    )
    #  Signing date
    signing_date_field = boldsign.FormField(
        id="SigningDate",
        fieldType="DateSigned",
         isRequired=True,
        pageNumber=1,
        bounds=boldsign.Rectangle(x=50, y=200, width=100, height=30),

    )
    # Payment date (seven days after signing date)
    payment_date_field = boldsign.FormField(
        id="PaymentDate",
        fieldType="Formula",
        pageNumber=1,
        bounds=boldsign.Rectangle(x=50, y=250, width=200, height=30),
        formulaFieldSettings=boldsign.FormulaFieldSettings(
            formulaExpression="AddDays([SigningDate], 7)",
        )
    )
    # Signer with all fields
    document_signer = boldsign.DocumentSigner(
        name="David",
        emailAddress="david@cubeflakes.com",
        signerType="Signer",
        formFields=[
            signature_field,
            textbox1,
            textbox2,
            formula_balance,
            signing_date_field,
            payment_date_field
        ]
    )
    send_for_sign = boldsign.SendForSign(
        title="Vehicle Sales Agreement",
        files=["Your file path.pdf"],
        signers=[document_signer]
    )
    document_created = document_api.send_document(send_for_sign)  
Enter fullscreen mode Exit fullscreen mode

PHP

    <?php require_once "vendor/autoload.php";
    use BoldSign\Configuration;
    use BoldSign\Api\DocumentApi;
    use BoldSign\Model\{
        FormField,
        Rectangle,
        DocumentSigner,
        SendForSign,
        FileInfo,
        FormulaFieldSettings,
        EditableDateFieldSettings
    };
    $config = new Configuration();
    $config->setApiKey('Your API Key');
    $document_api = new DocumentApi($config);
    // Signature field
    $signatureField = new FormField();
    $signatureField->setFieldType('Signature');
    $signatureField->setPageNumber(1);
    $signatureField->setBounds(new Rectangle([50, 50, 200, 25]));
    // Total vehicle value
    $textbox1 = new FormField();
    $textbox1->setId('textbox1');
    $textbox1->setFieldType('TextBox');
    $textbox1->setPageNumber(1);
    $textbox1->setBounds(new Rectangle([50, 100, 100, 30]));
    $textbox1->setValidationType('NumbersOnly');
    $textbox1->setIsRequired(true);
    // Deposit amount
    $textbox2 = new FormField();
    $textbox2->setId('textbox2');
    $textbox2->setFieldType('TextBox');
    $textbox2->setPageNumber(1);
    $textbox2->setBounds(new Rectangle([200, 100, 100, 30]));
    $textbox2->setValidationType('NumbersOnly');
    $textbox2->setIsRequired(true);
    // Signing date
    $signingDateField = new FormField();
    $signingDateField->setId('SigningDate');
    $signingDateField->setFieldType('DateSigned');
    $signingDateField->setPageNumber(1);
    $signingDateField->setBounds(new Rectangle([50, 200, 100, 30]));
    $signingDateField->setIsRequired(true);
    // Payment date (seven days after signing date)
    $paymentDate = new FormField();
    $paymentDate->setId('PaymentDate');
    $paymentDate->setFieldType('Formula');
    $paymentDate->setPageNumber(1);
    $paymentDate->setBounds(new Rectangle([50, 200, 200, 30]));
    $paymentSettings = new FormulaFieldSettings();
    $paymentSettings->setFormulaExpression('AddDays([SigningDate],7)');
    $paymentDate->setFormulaFieldSettings($paymentSettings);
    // Balance formula
    $balanceField = new FormField();
    $balanceField->setId('Balance');
    $balanceField->setFieldType('Formula');
    $balanceField->setPageNumber(1);
    $balanceField->setBounds(new Rectangle([50, 250, 200, 30]));
    $balanceSettings = new FormulaFieldSettings();
    $balanceSettings->setFormulaExpression('[textbox1] - [textbox2]'); 
    $balanceSettings->setDecimalPrecision(1);
    $balanceField->setFormulaFieldSettings($balanceSettings);
    // Signer
    $document_signer = new DocumentSigner();
    $document_signer->setName("David");
    $document_signer->setEmailAddress("david@cubeflakes.com");
    $document_signer->setSignerType("Signer");
    $document_signer->setFormFields([
        $signatureField, $textbox1, $textbox2, $signingDateField, $paymentDate, $balanceField
    ]);
    $send_for_sign = new SendForSign();
    $send_for_sign->setFiles(['Non Disclosure Agreement.pdf']);
    $send_for_sign->setSigners([$document_signer]);
    $send_for_sign->setTitle('Vehicle Sales Agreement');
    // Send document
    $document_created = $document_api->sendDocument($send_for_sign);
Enter fullscreen mode Exit fullscreen mode

Java

    ApiClient client = Configuration.getDefaultApiClient();
            client.setApiKey("Your API Key");
            DocumentApi documentApi = new DocumentApi(client);
            // Signature field
            FormField signatureField = new FormField();
            signatureField.setFieldType(FormField.FieldTypeEnum.SIGNATURE);
            signatureField.setPageNumber(1);
            signatureField.setBounds(new Rectangle().x(100f).y(100f).width(100f).height(50f));
            // Total vehicle value
            FormField vehicleValue = new FormField();
            vehicleValue.setId("textbox1");
            vehicleValue.setFieldType(FormField.FieldTypeEnum.TEXT_BOX);
            vehicleValue.setPageNumber(1);
            vehicleValue.setBounds(new Rectangle().x(50f).y(50f).width(120f).height(30f));
            vehicleValue.setValidationType(FormField.ValidationTypeEnum.NUMBERS_ONLY);
            // Deposit amount
            FormField depositAmount = new FormField();
            depositAmount.setId("textbox2");
            depositAmount.setFieldType(FormField.FieldTypeEnum.TEXT_BOX);
            depositAmount.setPageNumber(1);
            depositAmount.setBounds(new Rectangle().x(200f).y(50f).width(120f).height(30f));
            depositAmount.setValidationType(FormField.ValidationTypeEnum.NUMBERS_ONLY);
            // Signing date 
            FormField signingDate = new FormField();
            signingDate.setId("SigningDate");
            signingDate.setFieldType(FormField.FieldTypeEnum. DATE_SIGNED); 
            signingDate.setPageNumber(1);
            signingDate.setBounds(new Rectangle().x(50f).y(100f).width(180f).height(30f));
            signingDate.setDateFormat("MM/dd/yyyy"); 
            // Payment date
            FormField paymentDate = new FormField();
             paymentDate.setId("PaymentDate");
             paymentDate.setFieldType(FormField.FieldTypeEnum.FORMULA);
             paymentDate.setPageNumber(1);
             paymentDate.setBounds(new Rectangle().x(50f).y(140f).width(180f).height(30f));
            FormulaFieldSettings paymentSettings = new FormulaFieldSettings();
             paymentSettings.setFormulaExpression("AddDays([SigningDate],7)");
             paymentDate.setFormulaFieldSettings( paymentSettings);
            // Balance 
            FormField balanceField = new FormField();
            balanceField.setId("Balance");
            balanceField.setFieldType(FormField.FieldTypeEnum.FORMULA);
            balanceField.setPageNumber(1);
            balanceField.setBounds(new Rectangle().x(50f).y(200f).width(200f).height(30f));
            FormulaFieldSettings balanceSettings = new FormulaFieldSettings();
            balanceSettings.setFormulaExpression("[textbox1] - [textbox2]");  
            balanceSettings.setDecimalPrecision(2);
            balanceField.setFormulaFieldSettings(balanceSettings);
            // Signer
            DocumentSigner signer = new DocumentSigner();
            signer.setName("David");
            signer.setEmailAddress("david@cubeflakes.com");
            signer.setSignerType(DocumentSigner.SignerTypeEnum.SIGNER);
            signer.setFormFields(Arrays.asList(
                    signatureField,
                    vehicleValue,
                    depositAmount,
                    signingDate,
                    paymentDate,
                    balanceField
            ));
            // Send document
            SendForSign sendForSign = new SendForSign();
            File file = new File("Your file path.pdf"); 
            sendForSign.setFiles(Arrays.asList(file));
            sendForSign.setSigners(Arrays.asList(signer));
            sendForSign.setTitle("Vehicle Sales Agreement");
            DocumentCreated documentCreated = documentApi.sendDocument(sendForSign);
            System.out.println("Document created: " + documentCreated.getDocumentId());
Enter fullscreen mode Exit fullscreen mode

Node js

    import { DocumentApi, DocumentSigner, FormField, Rectangle, SendForSign } from "boldsign";
    import * as fs from 'fs';

    const documentApi = new DocumentApi();
    documentApi.setApiKey("Your API KEY");

    // Signature field
    const signatureField = new FormField();
    signatureField.fieldType = FormField.FieldTypeEnum.Signature;
    signatureField.pageNumber = 1;
    signatureField.bounds = new Rectangle();
    signatureField.bounds.x = 50;
    signatureField.bounds.y = 50;
    signatureField.bounds.width = 200;
    signatureField.bounds.height = 25;

    // Total vehicle value
    const textbox1 = new FormField();
    textbox1.id = "textbox1";
    textbox1.fieldType = FormField.FieldTypeEnum.TextBox;
    textbox1.pageNumber = 1;
    textbox1.bounds = new Rectangle();
    textbox1.bounds.x = 50;
    textbox1.bounds.y = 100;
    textbox1.bounds.width = 100;
    textbox1.bounds.height = 30;
    textbox1.validationType = "NumbersOnly";
    textbox1.isRequired = true;

    // Deposit amount
    const textbox2 = new FormField();
    textbox2.id = "textbox2";
    textbox2.fieldType = FormField.FieldTypeEnum.TextBox;
    textbox2.pageNumber = 1;
    textbox2.bounds = new Rectangle();
    textbox2.bounds.x = 200;
    textbox2.bounds.y = 100;
    textbox2.bounds.width = 150;
    textbox2.bounds.height = 30;
    textbox2.validationType = "NumbersOnly";
    textbox2.isRequired = true;

    // Balance formula
    const formulaBalance = new FormField();
    formulaBalance.id = "FormulaBalance";
    formulaBalance.fieldType = FormField.FieldTypeEnum.Formula;
    formulaBalance.pageNumber = 1;
    formulaBalance.bounds = new Rectangle();
    formulaBalance.bounds.x = 50;
    formulaBalance.bounds.y = 150;
    formulaBalance.bounds.width = 200;
    formulaBalance.bounds.height = 30;
    formulaBalance.formulaFieldSettings = {
        formulaExpression: "[textbox1] - [textbox2]",
        decimalPrecision: 1
    };

    // Signing date
    const signingDateField = new FormField();
    signingDateField.id = "SigningDate";
    signingDateField.fieldType = FormField.FieldTypeEnum.DateSigned;
    signingDateField.isRequired = true;
    signingDateField.pageNumber = 1;
    signingDateField.bounds = new Rectangle();
    signingDateField.bounds.x = 50;
    signingDateField.bounds.y = 200;
    signingDateField.bounds.width = 100;
    signingDateField.bounds.height = 30;

    // Payment date (seven days after signing date)
    const paymentDateField = new FormField();
    paymentDateField.id = "PaymentDate";
    paymentDateField.fieldType = FormField.FieldTypeEnum.Formula;
    paymentDateField.pageNumber = 1;
    paymentDateField.bounds = new Rectangle();
    paymentDateField.bounds.x = 50;
    paymentDateField.bounds.y = 250;
    paymentDateField.bounds.width = 200;
    paymentDateField.bounds.height = 30;
    paymentDateField.formulaFieldSettings = {
        formulaExpression: "AddDays([SigningDate], 7)",
    };
    // Signer with all fields
    const documentSigner = new DocumentSigner();
    documentSigner.name = "David";
    documentSigner.emailAddress = "david@cubeflakes.com";
    documentSigner.signerType = DocumentSigner.SignerTypeEnum.Signer;
    documentSigner.formFields = [
        signatureField,
        textbox1,
        textbox2,
        formulaBalance,
        signingDateField,
        paymentDateField
    ];

    const files = fs.createReadStream("Your File Path.pdf");

    const sendForSign = new SendForSign();
    sendForSign.title = "Vehicle Sales Agreement";
    sendForSign.signers = [documentSigner];
    sendForSign.files = [files];

    const documentCreated = documentApi.sendDocument(sendForSign);
Enter fullscreen mode Exit fullscreen mode

In the code examples above, replace the placeholders Your API Key and file path with your actual API key and the correct file path. In the formula expression section, use only the field ID. Once executed, the document will be sent to the specified signers, and any formula fields will automatically calculate values based on their input in real time, as shown below.

Formula Fields
Formula Fields

What best practices help formula fields work reliably?

  • Keep formulas simple: Avoid overly complex expressions for clarity.
  • Validate inputs: Use NumbersOnly or other validation types.
  • Use decimal precision wisely: Match financial standards in your industry.
  • Test templates: Send sandbox documents to confirm formulas work as expected.
  • Think about the user experience: Place formula fields logically so signers see results immediately.

Conclusion

Using formula fields via API brings a new level of automation to your e-signature workflows. Whether you’re in sales, finance, HR, or legal, this feature can help you deliver smarter, faster, and more reliable documents.

Ready to automate your document calculations? Try out formula fields with BoldSign today!

Sign up for a free sandbox account and explore our developer documentation to learn more about our APIs. For any assistance, visit our support portal to connect with our team.

Related blogs

Note: This blog was originally published at boldsign.com 

Top comments (0)