Building a full-featured HTML template
In this tutorial, we will show you how to build a full-featured HTML template and generate a document from it using the Inkit API. Be sure to understand how to create an HTML template and how to generate documents from the Inkit API before you start.
First, create an HTML template by doing the following:
-
In the Inkit web app, select Templates in the left sidebar and then click + Create.
-
In the Create Template page, select HTML from the File Type dropdown box, enter Invoice in the Template Name field and an optional description of the template in the Description field.
Then click + Add HTML.
Copy the following HTML to your clipboard.
<!DOCTYPE HTML> <html lang="en"> <head> test <meta charset="utf-8"> <title></title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;600;700&display=swap" rel="stylesheet"> <style> :root { --padding_horizontal:0in; /*page margins but padding is used for css reasons*/ --padding_verticle:0in; /*couldn't think of a clever name for top & bottom margins*/ --page_height:11in; --page_width:8.5in; } /* Body defines the document bounds */ body{ margin: 0; background-color: #478AFC; background-color: #2E71E5; background-color: #2B2C2F; background-color: #F9F9F9; display: flex; flex-grow: 0; flex-shrink: 0; flex-direction: column; font-weight: 400; font-style: normal; font-family: "Montserrat", sans-serif; } /* Page defines the page bounds */ .page{ position: relative; /* This will allow any position absolute tags to reference this as it's parent */ width: calc(var(--page_width) - (2 * var(--padding_horizontal))); height: calc(var(--page_height) - (2 * var(--padding_verticle))); padding-top: var(--padding_verticle); padding-bottom: var(--padding_verticle); padding-left: var(--padding_horizontal); padding-right: var(--padding_horizontal); background-color: white; display: flex; flex-direction: column; } /* Media query for editing ease - adds clear page delineation*/ @media only screen and (min-width: 11in) { #display_wrapper{ display:flex; flex-direction: column; justify-content: center; width:100%; justify-content: center; align-items: center; } .page{ margin-top: .1in; margin-bottom: .1in; filter: drop-shadow(0 0 0.75rem black); } } #background_image{ display:flex; flex-direction: column; height:100%; width:100%; background-position: center; background-repeat: no-repeat; background-size: contain; background-image: url('https://2906690.fs1.hubspotusercontent-na1.net/hubfs/2906690/Inkit%20Template%20Images/invoice_bg_1.png') } #logo{ position:absolute; top:28px; left:28px; height:.8in; width:2in; background-position: center; background-repeat: no-repeat; background-size: contain; background-image: url('https://2906690.fs1.hubspotusercontent-na1.net/hubfs/2906690/Inkit%20Template%20Images/logistica%20black.png') } #footer_call_container{ position:absolute; top:976px; left:222px; height:22px; width:140px; } #footer_link_container{ position:absolute; top:976px; left:410px; height:22px; width:140px; } #footer_location_container{ position:absolute; top:976px; left:608px; height:22px; width:140px; } #terms_container{ font-size: 9pt; position:absolute; top:770px; left:46px; height:75px; width:295px; } #header_container{ position:absolute; top:146px; margin-left:42px; margin-right:42px; width:calc(100% - 84px); text-align: center; font-weight: 400; font-size: 48px; color:#446FB6; color:#2B2C2F; } #details_bar{ position:absolute; top:220px; margin-left:42px; margin-right:42px; width:calc(100% - 84px); height:104px; text-align: center; font-weight: 400; font-size: 48px; color:#446FB6; } #details_left_container{ position: absolute; text-align: left; bottom:0; left:0; height:46px; width:295px; color:#2B2C2F; } #details_right_container{ position: absolute; text-align: right; right:0; bottom:0; height:46px; width:295px; color:#2B2C2F; } #details_top_container{ position: absolute; text-align: left; top:0; left:0; height:100px; width:100%; } #table_container{ top:364px; position:absolute; margin-left:42px; margin-right:42px; width:calc(100% - 84px); } .footer_item{ font-size: 7pt; color: white; font-weight:600; } .details *{ font-size: 9pt; } section .col{ margin:6px; display: table-cell; max-width: 200px; } header{ color:white; background-color: #446FB6; height:46px; font-size: 16pt; text-align: left; } header > .col > .header_col{ display:flex; flex-direction: row; align-items: center; height:46px; line-height: 20px; } row{ color:white; background-color: #446FB6; height:46px; font-size: 16pt; text-align: left; } .col_item{ color:#2B2C2F; align-items: center; vertical-align: middle; height:46px; font-size: 12pt; text-align: left; } section { display: table; width:100%; text-indent: 12px; } section > * { display: table-row; max-width: 200px; } section > * { display: table-row; max-width: 200px; } .bg_grey{ background-color: #F3F5F5; } .bg_black{ background-color: #2B2C2F; } .bg_white{ background-color: #FFFFFF; } .color_blue{ color: #446FB6; } .color_black{ color: #2B2C2F; } .color_white{ color: #FFFFFF; } .font_18{ font-size: 18pt; } .font_24{ font-size: 24pt; } .main_table > .row:nth-child(odd){ background-color: #E5E5E5; } .totals_container{ display: flex; flex-direction: row-reverse; } .totals{ width:50%; } .horizontal_bar{ width:100%; height:1px; } .sub_total{ text-align: right; } </style> </head> <body> <div id="display_wrapper"> <div class="page"> <div id="background_image"> <div id="logo"> </div> <div id="header_container"> INVOICE </div> <div class="details" id="details_bar"> <div id="details_top_container"> <b><span class="color_blue">INVOICE TO</span></b> <br> <b><span class="color_black font_24">{{client_company_name}}</span></b> </div> <div id="details_left_container"> {{client_address}} <br> Phone: {{client_phone}} <br> Email: {{client_email}} </div> <div id="details_right_container"> INVOICE NO: #{{invoice_number}} <br> DUE DATE: {{invoice_due_date}} <br> INVOICE DATE: {{invoice_issued_date}} </div> </div> <div id="table_container"> <div class="table_headers"></div> <section class="main_table"> <header> <div class="col"><div class="header_col"><div>ITEM</div></div></div> <div class="col">DESCRIPTION</div> <div class="col">QUANTITY</div> <div class="col">PRICE</div> <div class="col">TOTAL</div> </header> {% for product in products %} <div class="row"> <div class="col col_item">{{ product.title }}</div> <div class="col col_item">{{ product.description }}</div> <div class="col col_item">{{ product.quantity }}</div> <div class="col col_item">${{ product.unit_cost }}</div> <div class="col col_item">${{ product.unit_total }}</div> </div> {% endfor %} </section> <div class="totals_container"> <div class="totals"> <br> <div class="horizontal_bar bg_black"></div> <section> <div class="row"> <div class="col col_item sub_total">Sub Total:</div> <div class="col col_item">{{sub_total}}</div> </div> <div class="row"> <div class="col col_item sub_total">Tax (0%):</div> <div class="col col_item">{{tax_total}}</div> </div> <header> <div class="col col_item color_white"><div class="sub_total"><div>Grand Total:</div></div></div> <div class="col col_item color_white">{{grand_total}}</div> </header> </section> </div> </div> </div> <div id="totals_container"> </div> <div id="terms_container"> TERMS & CONDITIONS <br> This "Order Form" is entered into on the date of the last signature below. The Order Form, together with the Terms and Conditions, may also be referred to collectively as the "Agreement." </div> <div class="footer_item" id="footer_call_container"> {{primary_phone}} </br> {{secondary_phone}} </div> <div class="footer_item" id="footer_link_container"> {{primary_email}} </br> {{secondary_email}} </div> <div class="footer_item" id="footer_location_container"> Lorem Street 0124, 000 Set Lane Road </div> </div> </div> </div> </body> </html>
-
Paste the HTML into the Editor View panel and click Apply.
-
Click Save.
Next, write a script in either Python or Node.js, which creates merge parameters for the template that we created from a set of data and generates an invoice from it:
# Import the Inkit Python package
import inkit
from inkit.exceptions import InkitResponseException
# Import json package
import json
# Replace the string below with your API key
inkit.api_token = "ENTER YOUR API KEY"
try:
# Create a PDF document from a template
resp = inkit.Render.create(
# Specify the ID of the template
template_id = "ENTER YOUR TEMPLATE ID",
# Specify the data for the merge
merge_parameters = {"client_company_name": "Acme Templates", "client_address": "1234 Main St., New York, NY 10001", "client_phone": "212.555.1000", "client_email": "[email protected]", "invoice_number": "A234324", "invoice_due_date": "7/15/23", "invoice_issued_date": "7/15/23", "sub_total": "$65.00", "tax_total": "$0.00", "grand_total": "$65.00",
"products": [{"title": "Template A", "description": "Template A", "quantity": 2, "unit_cost": "10.00", "unit_total": "20.00"}, {"title": "Template B", "description": "Template B", "quantity": 3, "unit_cost": "5.00", "unit_total": "15.00"}, {"title": "Template C", "description": "Template C", "quantity": 1, "unit_cost": "20.00", "unit_total": "20.00"}, {"title": "Template D", "description": "Template D", "quantity": 5, "unit_cost": "2.00", "unit_total": "10.00"},],
"IMAGE1": "https://2906690.fs1.hubspotusercontent-na1.net/hubfs/2906690/Inkit%20Template%20Images/logistica%20black.png",},
# Specify the name of the PDF file
destinations = {"inkit_storage": {"name": "New Invoice"}}
)
# Print the JSON repsonse of the API call
print(json.dumps(resp.data, indent = 3))
except InkitResponseException as err:
# Print any error
print(err.response.data)
// Import the Inkit Node.js package
const Inkit = require("inkit");
// Replace the string below with your API key
Inkit.apiToken = "ENTER YOUR API KEY";
// Call the PDF renderer
createRender();
// Create a PDF document from a template
async function createRender() {
try {
const result = await Inkit.Render.create({
// Specify the ID of the template
templateId: 'ENTER YOUR TEMPLATE ID',
// Specify the data for the Name field
mergeParameters:
{"client_company_name": "Acme Templates", "client_address": "1234 Main St., New York, NY 10001", "client_phone": "212.555.1000", "client_email": "[email protected]", "invoice_number": "A234324", "invoice_due_date": "7/15/23", "invoice_issued_date": "7/15/23", "sub_total": "$65.00", "tax_total": "$0.00", "grand_total": "$65.00",
"products": [{"title": "Template A", "description": "Template A", "quantity": 2, "unit_cost": "10.00", "unit_total": "20.00"}, {"title": "Template B", "description": "Template B", "quantity": 3, "unit_cost": "5.00", "unit_total": "15.00"}, {"title": "Template C", "description": "Template C", "quantity": 1, "unit_cost": "20.00", "unit_total": "20.00"}, {"title": "Template D", "description": "Template D", "quantity": 5, "unit_cost": "2.00", "unit_total": "10.00"},],
"IMAGE1": "https://2906690.fs1.hubspotusercontent-na1.net/hubfs/2906690/Inkit%20Template%20Images/logistica%20black.png",},
// Specify the name of the PDF file
destinations: {"inkit_storage": {"name": "New Invoice"}}
});
// Print the JSON response of the API call
console.log(JSON.stringify(result.data, null, 3));
} catch (error) {
// Print any error
console.error(error.response.status, error.response.statusText);
}
}
Finally, in a terminal or command prompt execute the script by running one of the following commands:
python [script]
(Python)node [script]
(Node.js)
When viewing the generated invoice in the Inkit web app, you should see something like this:
Updated 12 months ago