# Document Information

> Check a template before a merge: read its merge fields, nested merge blocks and properties with the info endpoint or DocumentInfo, and list server printers.

- **Product:** DS Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** DS Server > Document Processing > Document Information
- **2596 words**
- **Web URL:** https://docs.textcontrol.com/ds-server/document-processing/document-info/
- **LLMs URL:** https://docs.textcontrol.com/ds-server/document-processing/document-info/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/ds-server/document-processing/document-info/llms-full.txt

---

Before your application merges data into a template, it often needs to know what the template expects: which merge fields it contains, which merge blocks repeat and how they are nested. The info endpoint of the DocumentProcessing Web API reads a document and returns this structure together with the document properties, such as the title and the author, without changing the document. A second endpoint lists the printers installed on the server, whose names you can pass as the formatting printer of a merge.

### How Document Information Works

The endpoint is [POST /documentprocessing/document/info](https://docs.textcontrol.com/ds-server/reference/web-api/documentprocessing/document-info/post/llms-full.txt):

| Part of the request | Content |
|---|---|
| Body | The document as a Base64 string in a JSON string, with the content type `application/json` |
| Response | A JSON object of the type `DocumentInfo` |

The response describes the document as a whole and its merge structure:

| Property | Content |
|---|---|
| `mergeFields` | The merge fields of the document. Each has a `name`, and the formats and texts `dateTimeFormat`, `numericFormat`, `preserveFormatting`, `text`, `textBefore` and `textAfter` |
| `mergeBlocks` | The merge blocks, each with its `name`, its own `mergeFields` and the `mergeBlocks` nested in it |
| `userDocumentProperties` | The user-defined document properties, as names and values |
| `documentTitle`, `documentSubject`, `documentKeywords` | The title, the subject and the keywords, `documentKeywords` as an array of strings |
| `author`, `creatorApplication` | The author and the application that created the document |
| `creationDate`, `lastModificationDate` | The dates of creation and of the last change |

A merge field is a placeholder that a merge replaces with a value from the data, and a merge block is a part of the template that the merge repeats for each record of an array, such as a table row per order item. The fields of a block are listed with the block, and each block lists only its own fields and blocks, not those of the blocks nested in it. [Merging Templates](https://docs.textcontrol.com/ds-server/document-processing/mail-merge/llms-full.txt) shows how the structure maps to JSON data.

Every request needs an access token, as [Authentication](https://docs.textcontrol.com/ds-server/document-processing/authentication/llms-full.txt) describes.

### Read the Structure of a Template With curl

The following commands send *template.docx* to the info endpoint and print the merge fields and blocks:

```bash
DS=http://localhost:5000
TOKEN="<access_token>"

# Wrap the Base64 string of the template in a JSON string
base64 -w 0 template.docx | jq -Rs . > template.json

curl --request POST "$DS/documentprocessing/document/info" \
  --header "Authorization: Bearer $TOKEN" \
  --header "Content-Type: application/json" \
  --data-binary @template.json \
  --output info.json

jq '{mergeFields: [.mergeFields[].name], mergeBlocks}' info.json
```

The commands work as follows:

- `base64 -w 0` encodes the file without line breaks, and `jq -Rs .` makes a JSON string of it. The body is this string alone, not an object around it.
- The response is JSON, not Base64: *info.json* holds the `DocumentInfo` object as it is.
- The last `jq` command prints the names of the top-level merge fields and the merge blocks with their fields.

When DS Server runs on Linux, the Core build supports the document formats DOCX, HTML, PDF and XLSX only, as [Limits on Linux](https://docs.textcontrol.com/ds-server/overview/core-classic/#limits-on-linux) lists. Send templates in one of these formats there.

### Read the Structure of a Template With .NET

The package `TXTextControl.DocumentServices.DocumentProcessing` returns the response as a `DocumentInfo` object. The following console application prints the properties and the merge structure of *template.docx*, with nested blocks indented:

```csharp
using TXTextControl.DocumentServices.DocumentProcessing;
using TXTextControl.DocumentServices.DocumentProcessing.OAuth;

var oauthSettings = new OAuthSettings("<client ID>", "<client secret>");
var documentProcessing = new DocumentProcessing("http://localhost:5000", oauthSettings);

byte[] template = File.ReadAllBytes("template.docx");
DocumentInfo info = await documentProcessing.Info(template);

Console.WriteLine($"Title: {info.DocumentTitle}, author: {info.Author}");

// Merge fields of the document
foreach (MergeField field in info.MergeFields)
{
    Console.WriteLine($"Field: {field.Name}");
}

// Merge blocks with their fields and nested blocks
foreach (MergeBlock block in info.MergeBlocks)
{
    PrintBlock(block, 0);
}

void PrintBlock(MergeBlock block, int level)
{
    string indent = new string(' ', level * 2);
    Console.WriteLine($"{indent}Block: {block.Name}");

    foreach (MergeField field in block.MergeFields)
    {
        Console.WriteLine($"{indent}  Field: {field.Name}");
    }

    foreach (MergeBlock nested in block.MergeBlocks)
    {
        PrintBlock(nested, level + 1);
    }
}
```

The code works as follows:

- The `DocumentProcessing` constructor takes the service URL and the credentials of a security profile that allows the client credentials grant type, and requests an access token.
- `Info` sends the document as a byte array and returns a `DocumentInfo`. Its properties are those of the JSON response in Pascal case: `MergeFields`, `MergeBlocks`, `DocumentTitle`, `Author`, `CreationDate` and so on.
- `MergeBlock` has a `Name`, its `MergeFields` and its nested `MergeBlocks`, so the method `PrintBlock` calls itself for each nested block.

The classes are listed in the [DocumentProcessing namespace](https://docs.textcontrol.com/ds-server/reference/dotnet-api/txtextcontrol-documentservices-documentprocessing/llms-full.txt) of the .NET API.

### Check a Template Before a Merge

The merge structure lets your application check a template before it merges it, for example a template that a user uploaded:

- **Compare the field names with your data.** Merge fields are named like the properties of a record. Collect the names from `mergeFields` and from every block, and compare them with the keys of your JSON records.
- **Match blocks with arrays.** A merge block is repeated for each element of a nested array, such as a block `OrderItems` for the order items of a customer. Check that your data has an array for each block.
- **Build a form or a data mapping.** The field names are the list of values a user has to provide, and `dateTimeFormat` and `numericFormat` show how a field formats its value.

### List the Printers Installed on the Server

A merge can format the document with the text dimensions and capabilities of a printer, the *formatting printer*. [GET /documentprocessing/document/installedprinters](https://docs.textcontrol.com/ds-server/reference/web-api/documentprocessing/document-installedprinters/get/llms-full.txt) returns the printers installed on the server that runs DS Server, as an array of `PrinterInfo` objects:

```bash
curl --request GET "$DS/documentprocessing/document/installedprinters" \
  --header "Authorization: Bearer $TOKEN"
```

The merge settings of the merge and find-and-replace endpoints have a `formattingPrinter` property that takes the name of one of these printers, as the reference of [POST /documentprocessing/document/merge](https://docs.textcontrol.com/ds-server/reference/web-api/documentprocessing/document-merge/post/llms-full.txt) lists. The endpoint was added in version 3.3.0; the changelog of that version names it `document/printers`, but DS Server 5.0.2 answers that address with `404 Not Found` and serves the list at `document/installedprinters`.

In .NET, the method `InstalledPrinters` of the package returns the list as a `PrinterInfo` array, and the `Name` property of each element holds the name of the printer:

```csharp
PrinterInfo[] printers = await documentProcessing.InstalledPrinters();

foreach (PrinterInfo printer in printers)
{
    Console.WriteLine(printer.Name);
}
```

In version 5.0.0 of the package, a refused request of this method throws a plain `Exception`, not the `ServiceRequestException` of the other methods, and the exception has no status code. [Errors and Status Codes](https://docs.textcontrol.com/ds-server/document-processing/errors/#handle-errors-in-net) shows how the other methods report errors.

### Next Steps

- [Merging Templates](https://docs.textcontrol.com/ds-server/document-processing/mail-merge/llms-full.txt): merge the template with JSON data whose names match its fields and blocks.
- [Find and Replace](https://docs.textcontrol.com/ds-server/document-processing/find-replace/llms-full.txt): replace text in a template that has no merge fields.
- [PDF Form Fields](https://docs.textcontrol.com/ds-server/document-processing/pdf-forms/llms-full.txt): read the form fields of a PDF document.
- [Errors and Status Codes](https://docs.textcontrol.com/ds-server/document-processing/errors/llms-full.txt): what a refused request means.

---

## Nearby

- **Previous:** [Find and Replace](https://docs.textcontrol.com/ds-server/document-processing/find-replace/llms-full.txt)
- **Next:** [Thumbnails](https://docs.textcontrol.com/ds-server/document-processing/thumbnails/llms-full.txt)
