Generating documents

Generate PDF or DOCX from a template and your data — through the GUI or the RESTful API. You can also bulk-import data with CSV files.

From the GUI

Enter your data first (see the end-user guide), then on the Templates screen choose a template, select the data, optionally change the language or output format, and click Generate. The document opens in a new tab and is saved to the archive.

Additional settings available at generation time: Language (localisation override), Output file format (PDF/DOCX), Advanced signature (PFX), and Encryption (password). See Signing & verification.

From the RESTful API

API generation resembles the GUI, with two differences: you do not need pre-entered data (send it inline), and for advanced signing the password-protected PFX must already be stored in the user's profile (you cannot upload a PFX through the API). A public Postman collection is available against the demo environment.

Step 1 — Authenticate

[HTTP POST] [URL of DocsNG]/api/Account/Login with parameters Username and Password. On success the API returns a Bearer token.

curl -X POST "$BASE/api/Account/Login?username=$U&password=$P"

Step 2 — Generate

[HTTP POST] [URL of DocsNG]/api/Document/GenerateDocumentFromJson

Query parameters:

ParameterDescription
culture (string)Localisation override, e.g. en-US, nl-NL, de-DE
templateId (integer)The id of the template in DocsNG
outputType (integer)1 = DOCX, 2 = PDF
encryptPwd (string)Password for PDF encryption
pfxPwd (string)Password of the PFX certificate stored in the user profile, used for advanced signing

Header: Accept-Language sets the language of API response messages (en, es, de, nl, tr, fr, it, pt).

Request body: a JSON array. Each element is one document to generate, described by its model, fields, and nested relations. The response is the id of the generated document.

Structure:

[
  {
    "Id": 201,          // your identifier for this generation
    "ModelId": 3,       // data model id in DocsNG
    "Name": "Invoice",  // data model name
    "Fields": [
      { "Name": "Number", "Value": "INVFromAPI1",
        "Type": "String", "IsRequired": "Y" }
      // Type: String | DateTime | Currency | Double | Boolean
      // IsRequired: Y | N
    ],
    "Relations": [      // nested related models
      {
        "Id": 1, "ModelId": 1, "Name": "Customer",
        "Fields": [ { "Name": "Name", "Value": "Customer From API",
                      "Type": "String", "IsRequired": "Y" } ],
        "Relations": []
      }
    ]
  }
]

A fuller invoice example (one invoice, one customer, two items):

[
  {
    "Id": 201, "ModelId": 3, "Name": "Invoice",
    "Fields": [
      { "Name": "Number",        "Value": "INVFromAPI1",              "Type": "String",   "IsRequired": "Y" },
      { "Name": "Date",          "Value": "2023-10-06T09:00:00.594Z", "Type": "DateTime", "IsRequired": "Y" },
      { "Name": "DueDate",       "Value": "2023-10-31T09:00:00.594Z", "Type": "DateTime", "IsRequired": "Y" },
      { "Name": "CustomerVATNr", "Value": "TestVat",                  "Type": "String",   "IsRequired": "Y" },
      { "Name": "UntaxedAmount", "Value": "100",                      "Type": "Currency", "IsRequired": "Y" },
      { "Name": "TaxAmount",     "Value": "21",                       "Type": "Currency", "IsRequired": "Y" },
      { "Name": "Total",         "Value": "121",                      "Type": "Currency", "IsRequired": "Y" }
    ],
    "Relations": [
      { "Id": 1, "ModelId": 1, "Name": "Customer",
        "Fields": [
          { "Name": "Name",    "Value": "Customer From API", "Type": "String", "IsRequired": "Y" },
          { "Name": "Address", "Value": "Test Street 33",    "Type": "String", "IsRequired": "Y" },
          { "Name": "City",    "Value": "Rotterdam",         "Type": "String", "IsRequired": "Y" },
          { "Name": "Country", "Value": "Netherlands",       "Type": "String", "IsRequired": "Y" }
        ], "Relations": [] },
      { "Id": 100, "ModelId": 2, "Name": "InvoiceItems",
        "Fields": [
          { "Name": "Description", "Value": "Pizza 1", "Type": "String",   "IsRequired": "Y" },
          { "Name": "Quantity",    "Value": "2",       "Type": "Double",   "IsRequired": "Y" },
          { "Name": "UnitPrice",   "Value": "20",      "Type": "Currency", "IsRequired": "Y" },
          { "Name": "Amount",      "Value": "40",      "Type": "Currency", "IsRequired": "Y" }
        ], "Relations": [] },
      { "Id": 101, "ModelId": 2, "Name": "InvoiceItems",
        "Fields": [
          { "Name": "Description", "Value": "Pizza 2", "Type": "String",   "IsRequired": "Y" },
          { "Name": "Quantity",    "Value": "1",       "Type": "Double",   "IsRequired": "Y" },
          { "Name": "UnitPrice",   "Value": "10",      "Type": "Currency", "IsRequired": "Y" },
          { "Name": "Amount",      "Value": "10",      "Type": "Currency", "IsRequired": "Y" }
        ], "Relations": [] }
    ]
  }
]

Step 3 — Download

[HTTP GET] [URL of DocsNG]/api/Document/DownloadDocument with id (the id returned from Step 2) and jwtToken. The response is the binary of the generated document.

See the API reference for the full endpoint list.

Output formats & accessibility

Generate PDF, DOCX or HTML from one template. For records and compliance you can also produce PDF/A (archival) and PDF/UA (accessible, tagged) output. Signing and encryption apply to PDF output.

At scale & from your systems

For high volume, use batch generation and the async job API. To pull data from SQL, REST/OData or webhooks instead of CSV/JSON, see data connectors. Across a run, DocsNG applies the culture per record for per-recipient language.

Bulk data upload with CSV (GUI)

Import large amounts of data via CSV.

Prerequisites:

  • By default DocsNG uses a comma (,) as the list delimiter. If your locale differs, see Custom list delimiter below.
  • The first row must contain the data-model field names. Columns that don't match a field are ignored on import.
  • Dates must be in JSON date format (see below).
  • To import relationships, include the relationship search columns (see Relationship mapping).
  • For special characters (ö, ü, ç, ı …), save the file as CSV UTF-8 in Excel.

Steps: log in, open the target data model, click the upload button, select your CSV file, click OK, then review the imported data for accuracy.

Custom list delimiter

An administrator can change the delimiter: Settings → Server Settings → CSV Delimiter. For example, enter ; to use a semicolon instead of a comma, then save. The setting applies instance-wide.

Formatting dates as JSON date in Excel

JSON dates follow ISO 8601: YYYY-MM-DDTHH:mm:ss.sssZ. In Excel, convert a date in cell A1 with:

=TEXT(A1, "yyyy-mm-ddTHH:mm:ss.sssZ")

For example, 10/15/2023 14:30 becomes 2023-10-15T14:30:00.000Z. A handy trick: rename your source column header to something the model doesn't have (e.g. BirthdayIn), add a new column named exactly like the model field (Birthday) containing the =TEXT(…) formula. On import the unmatched BirthdayIn column is ignored and the JSON-formatted Birthday column is imported.

Bulk-upload relationship mapping

Relationships are established with a search. For each relationship, add two columns to the CSV:

  • Search field column: header = {ModelName}IdField (e.g. CustomerIdField); value = the exact field name to search on (e.g. Name).
  • Search value column: header = {ModelName}{FieldName} (e.g. CustomerName); value = the value to match (e.g. Hans Janssen).

Example columns in an Invoice CSV:

CustomerIdFieldCustomerNameInvoiceItemsIdFieldInvoiceItemsDescription
NameHans JanssenDescriptionPizza

This links each invoice to the Customer whose Name is Hans Janssen and to the InvoiceItem whose Description is Pizza.


Need help? Contact us or try the live demo.