Automate eSignature and document workflows for purchase orders: A developer’s guide
At many companies, it’s common to have the ability to generate purchase orders from data housed in your CRM, ERP, or backend systems. What’s missing is automating the process of getting those documents signed and approved following your company’s business practices.
You need a solution that offers seamless integration with your existing systems and is easy to customize to match your company’s unique business processes. Efficiency in implementation is a plus; the quicker you can set up and automate your processes, the better.
Electronic signature security and compliance
The solution also needs to comply with eSignature laws and regulations and ensure data security to protect confidential documents and information.
eSignature: E-Sign Act, UETA
Data Privacy: GDPR, CPRA, HIPAA-ready
Data Security: SOC 2 Type II, SHA-256 encryption
How to dynamically generate purchase orders and embed eSignature in your app
In this tutorial, we’ll demonstrate how to generate professional documents populated with backend data using Document Automation Hub. We’ll show how to conditionally display terms and conditions based on region, add signature, and seamlessly integrate document workflow and eSignature inside your Next.js or React applications.
Purchase Order app
A basic React app simulating data retrieval from an existing system.
Purchase Order document
A DOCX file, that will be used to dynamically generate the purchase order with the provided data. It will conditionally display terms and conditions based on the selected region.
Embedded signing
Embed eSignature in your application, website or CRM.
Setup: Download the code
We’ll use a Next.js app to simulate data retrieval from your backend systems by passing data in via an HTML form. Download the code here or clone it to a local repository.
git clone https://github.com/edshin24/purchase-order-app
Key concepts
We’ll use Document Automation Hub, an API for automating document workflows, to dynamically pre-fill the document, conditionally display terms and conditions, and generate a link for document signing.
Organization | The environment (or workspace) where you manage Templates and Flows, upload and create documents and forms, organize webhook events, and users. |
Template | A workflow configuration containing one or more documents or forms. |
Flow | An actionable copy of all documents and forms in a Template. |
Authentication: JWT Grant
- Create a free developer account
- Log into the Automation Hub Dashboard
- Click Add Application, and enter:
Application name | Purchase Order App |
Application URL | http://www.test.com |
Generate JWT Token
- Click on the application you just created → under Recent Applications
- Click JWT Token
- Create RSA → Copy your private key
- Click “Generate token” → Paste your Private key and set the Expiration date
Copy the JSON Web Token → We’ll need this to make our API calls.
Document generation
Document generation gives you the ability to dynamically generate PDFs from Microsoft Word documents by adding custom variables that are later populated with specific data.
Automating this step can add time savings, accuracy and consistency to your documents. And using a Word document gives you full control over branding so you can exactly match your business requirements and design.
Dynamic content
Our purchase order contains text tags, conditionals, and a signature field.
Text Tags | {{Client_Name}} {{Order_Date}} {{Address}} {{City}}, {{State}} {{Zip}} {{Phone}} | Custom variables we’ll use to pre-fill our document with data we pass in |
Conditionals | {{if(Terms=‘CA’)}} {{else((Terms=‘NY’)}} {{endif}} | Add conditional logic to generate different terms and conditions per region |
Fillable Fields | {{t:s;r:n;l:”Signature_1″;}} | To collect user input, like a signature field |
See “IT Purchase Order.docx” in the root directory of the project to see how it works, or manually add them to your own Word document to get hands-on experience.
Tip: Use straight quotes (not curly quotes!) when adding the signature field.
Base64 encode
To prepare the document(s) for upload, we need to encode them in Base64 format.
For simplicity, “IT Purchase Order.docx” has already been encoded as “IT Purchase Order.docx.base64”.
To Base64 encode your documents:
- Use a free online Base64 encoder.
- Use encodeDocxToBase64.js to encode your documents on your local machine.
node encodeDocxToBase64.js <path-to-file.docx>
Note: You can find “IT Purchase Order.docx.base64” and “encodeDocxToBase64.js” in the root directory of the project.
Create a Template
Next, let’s create the Template. A template represents the workflow configuration, documents and forms for your workflow.
Let’s take a look at the curl request example from the docs to see how it works:
curl --request POST \
--url https://api.airslate.io/v1/organizations/organization_id/templates \
--header 'Accept: application/json' \
--header 'Authorization: Bearer undefined' \
--header 'Content-Type: application/json' \
--data '{
"name": "My Template",
"description": "Template for HR Office",
"redirect_url": "https://www.pdffiller.com/?mode=view"
}'
…/v1/organizations/organization_id/templates | API endpoint: Requires “organization_id” |
Accept: application/json | Response in JSON format |
Authorization: Bearer undefined | Authentication |
Content-Type | Request in JSON format |
data ‘{ “name”: “My Template”, “description”: “Template for HR Office”, “redirect_url”: “https://www.pdffiller.com” }’ | Template name, description, and redirect_url |
Organization ID
To get the organization ID, let’s take a look at the curl request example from the docs:
curl --request GET \
--url https://api.airslate.io/v1/organizations \
--header 'Accept: application/json' \
--header 'Authorization: Bearer undefined'
This call gets all organizations we belong to. We’re also going to take care of a few housekeeping items here to simplify the rest of our API calls.
Optional: You can log in with your free developer account to create an organization (workspace) at https://www.airslate.com/.
Implement with Axios and Next.js
It’s straightforward to map the example curl request using axios.
- endpoint: url + query parameters
- options: headers for authentication and expected data formats
- payload: data; none in this case
// api.js -> API calls to https://api.airslate.io/v1
const getOrganization = async () => {
try {
const endpoint = `${BASE_URL}/organizations?per_page=100`;
const response = await axios.get(endpoint, { headers: await getHeaders() });
return response.data.data.find(org => org.name === ORGANIZATION);
. . .
// getHeaders()
const getHeaders = async () => {
const accessToken = await getAccessToken();
return {
'Accept': 'application/json',
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
};
};
Get Access Token
We’re also going to use this initial API call to check if we have a valid access token and obtain a new one if we don’t have one or if it’s expired.
// api.js -> getOrganization (cont’d)
. . .
} catch (error) {
if (error.response && error.response.status === 401) {
console.warn('Unauthorized request when fetching organizations. Attempting token refresh.');
const newToken = await obtainAccessToken();
setAccessToken(newToken);
Create a Template with Axios
Now that we have the organization ID and access token, we’ll create the template by passing in the organization ID, name, description, and redirect_url.
const TEMPLATE = "Purchase Order Template";
const REDIRECT_URL = "https://www.google.com";
const createTemplate = async (organizationId) => {
const endpoint = `${BASE_URL}/organizations/${organizationId}/templates`;
const payload = {
name: TEMPLATE,
description: "Purchase Order Template",
redirect_url: REDIRECT_URL
};
const response = await axios.post(endpoint, payload, { headers: await getHeaders() });
return response.data;
};
Upload document
After creating the template, we’ll upload one or more documents or forms. In our case, we’re uploading a Word document so we’ll set type to “DOC_GENERATION” and pass in our Base64 encoded document.
const DOCUMENT = "IT Purchase Order.docx";
const uploadDocument = async (organizationId, templateId) => {
const endpoint = `${BASE_URL}/organizations/${organizationId}/templates/${templateId}/documents`;
const payload = {
name: DOCUMENT,
type: "DOC_GENERATION",
content: getBase64Content()
};
return await axios.post(endpoint, payload, { headers: await getHeaders() });
};
const getBase64Content = () => {
const filePath = path.join(process.cwd(), 'IT Purchase Order.docx.base64');
const base64Content = fs.readFileSync(filePath, 'utf-8');
return base64Content;
};
Pre-Fill via API Bot
Document Automation Hub leverages airSlate to handle the embedded signing session. To configure the signing session to pre-fill our documents via the API:
- Log into airslate.com using your free developer account
- Click All Templates
- Click Configure Template
4. Click All Bots (lower right of screen)
5. Click Add Bot
6. Search for “Pre-fill via API”
7. Click Install Bot
8. Click Publish
Create a Flow
Next, we’ll create a Flow → an actionable copy of our documents and forms. This is the step where we’ll pass in our data to dynamically generate our document.
Note: orderData contains the data from the HTML form.
const createFlow = async (organizationId, templateId, document, orderData) => {
const endpoint = `${BASE_URL}/organizations/${organizationId}/templates/${templateId}/flows`;
const payload = {
documents: [
{
id: document.id,
fields: [
{
"id": getFieldIdByName(document, "Order_Date"),
"type": "date",
"name": "Order_Date",
"value": orderData.date,
"placeholder": ""
},
...
{
"id": getFieldIdByName(document, "Client_Name"),
"type": "text",
"name": "Client_Name",
"value": orderData.clientName,
"placeholder": ""
}
]
}
]
};
const response = await axios.post(endpoint, payload, { headers: await getHeaders() });
return response.data;
};
Create a link to the Flow
Now we’re ready to send out our first Flow. The documents or forms provided in the link can only be submitted once and expires after a set duration of time (in minutes).
Note: roleId is returned in the response when we create a Flow.
// createPurchaseOrder.js
roleId = flow.available_roles[0].id;
// api.js
const distributeFlow = async (organizationId, templateId, flowId, roleId) => {
const endpoint = `${BASE_URL}/organizations/${organizationId}/templates/${templateId}/flows/${flowId}/share`;
const payload = {
data: [
{
auth_method: "none",
expire: 60,
role_id: roleId
}
]
};
return await axios.post(endpoint, payload, { headers: await getHeaders() });
};
Embed eSignature in your app
We’ll use the URL we retrieved in the last step to embed the signing session within our app.
return (
<div style={{ width: '100%', height: '100vh' }}>
<div className="bg-blue-600 p-5">
<h1 className="text-2xl text-white">Technology Solutions, Inc.</h1>
</div>
<iframe
src={embedUrl}
style={{
border: 'none',
width: '100%',
height: '100%',
overflow: 'hidden'
}}
title="Embedded Docx"
></iframe>
Free Developer Account
Document Automation Hub is a useful addition to your toolkit with a suite of API capabilities that go beyond eSignature, and includes document workflow, dynamic webforms, embedded PDF editing, and PDF tools that easily integrate with your existing systems.
Head over to our developer page to create a free developer account and get 250 flows for free. And check out our Stack Overflow community to post questions on this demo or on how to use any of our APIs. We regularly check in on questions asked by developers there.
Document Automation Hub docs:
- Document Generation
- Get Organizations
- Create Template
- Upload Document
- Create a Flow → Pre-fill document with specific data
- Create a Flow Link → Embed or send for signature
Happy coding! We hope this article helps you automate document workflows and eSignature for your purchase orders.
- Electronic signature security and compliance
- How to dynamically generate purchase orders and embed eSignature in your app
- Setup: Download the code
- Key concepts
- Authentication: JWT Grant
- Document generation
- Dynamic content
- Base64 encode
- Create a Template
- Organization ID
- Implement with Axios and Next.js
- Get Access Token
- Create a Template with Axios
- Upload document
- Pre-Fill via API Bot
- Create a Flow
- Create a link to the Flow
- Embed eSignature in your app
- Free Developer Account