How to Send an Envelope with Templates
This guide demonstrates how to create envelopes using pre-configured templates with Blueink's API v2. You'll learn how to use both document templates and envelope templates to streamline your signing workflows and eliminate the need to upload files for recurring document types.
Overview
Templates in Blueink allow you to reuse document structures and envelope configurations:
- Document Templates - Pre-configured documents with fields that can be reused across multiple envelopes
- Envelope Templates - Complete envelope configurations including documents, signers, and field assignments
Envelopes created from templates are automatically sent in the background after creation, though they initially show pending status while processing.
Prerequisites
Before you begin, ensure you have:
- A Blueink account with API access
- Your API key (available in the Blueink Dashboard under Apps)
- Pre-configured templates in your Blueink account
- Template IDs for the templates you want to use
- Basic knowledge of HTTP requests and your chosen programming language
If you don't have an API key yet, visit the Authentication guide to learn how to obtain one.
When using is_test: true
, envelopes can only be sent to email addresses that belong to users in your Blueink account. Make sure the signer email addresses match existing users in your account when testing.
Step 1: Prepare Your Environment
Authentication Setup
All requests to the Blueink API require authentication using your API key in the Authorization header:
Authorization: Token YOUR_API_KEY_HERE
Required Information
For this guide, you'll need:
- Template ID: The ID of your document template (UUID format) or envelope template (T-xxxxxxxxxx format)
- Signer information: Name and email address of the person who will sign
- Template assignments: Mapping between template roles and actual signers
Step 2: Create Envelope with Document Template
Document templates are pre-configured documents with fields that you can reuse. When using a document template, you specify the template ID and assign template roles to actual signers.
- Python
- JavaScript (Node.js)
import requests
import json
# Configuration
API_KEY = "your_api_key_here"
BASE_URL = "https://api.blueink.com/api/v2"
TEMPLATE_ID = "your-template-uuid-here" # UUID format
# Headers for authentication
headers = {
"Authorization": f"Token {API_KEY}",
"Content-Type": "application/json"
}
# Bundle request data using document template
bundle_request = {
"label": "Contract from Template",
"is_test": True, # Set to False for production
# "status": "dr", # Uncomment to create as draft (default is pending)
"packets": [
{
"key": "signer-1",
"name": "John Doe",
"email": "[email protected]",
"deliver_via": "email"
}
],
"documents": [
{
"key": "template-doc",
"template_id": TEMPLATE_ID,
"assignments": [
{
"role": "customer", # Template role name
"signer": "signer-1" # Packet key
}
],
"field_values": [ # Optional: Pre-fill template fields
{
"key": "company_name",
"initial_value": "ACME Corporation"
},
{
"key": "contact_person",
"initial_value": "John Doe"
}
]
}
]
}
try:
# Create the envelope with document template
response = requests.post(
f"{BASE_URL}/bundles/",
headers=headers,
json=bundle_request
)
if response.status_code == 201:
bundle = response.json()
print(f"✅ Envelope created successfully!")
print(f"Bundle ID: {bundle['id']}")
print(f"Status: {bundle['status']}")
print(f"📧 Envelope will be automatically sent to signers by background processes.")
print(f"View URL: https://app.blueink.com/bundles/{bundle['id']}")
else:
print(f"❌ Error creating envelope: {response.status_code}")
print(f"Response: {response.text}")
except Exception as e:
print(f"❌ Error: {e}")
const axios = require('axios');
// Configuration
const API_KEY = 'your_api_key_here';
const BASE_URL = 'https://api.blueink.com/api/v2';
const TEMPLATE_ID = 'your-template-uuid-here'; // UUID format
// Bundle request data using document template
const bundleRequest = {
label: 'Contract from Template',
is_test: true, // Set to false for production
// status: 'dr', // Uncomment to create as draft (default is pending)
packets: [
{
key: 'signer-1',
name: 'John Doe',
email: '[email protected]',
deliver_via: 'email'
}
],
documents: [
{
key: 'template-doc',
template_id: TEMPLATE_ID,
assignments: [
{
role: 'customer', // Template role name
signer: 'signer-1' // Packet key
}
],
field_values: [ // Optional: Pre-fill template fields
{
key: 'company_name',
initial_value: 'ACME Corporation'
},
{
key: 'contact_person',
initial_value: 'John Doe'
}
]
}
]
};
async function createEnvelopeWithDocumentTemplate() {
try {
const response = await axios.post(
`${BASE_URL}/bundles/`,
bundleRequest,
{
headers: {
'Authorization': `Token ${API_KEY}`,
'Content-Type': 'application/json'
}
}
);
if (response.status === 201) {
const bundle = response.data;
console.log('✅ Envelope created successfully!');
console.log(`Bundle ID: ${bundle.id}`);
console.log(`Status: ${bundle.status}`);
console.log('📧 Envelope will be automatically sent to signers by background processes.');
console.log(`View URL: https://app.blueink.com/bundles/${bundle.id}`);
return bundle;
}
} catch (error) {
if (error.response) {
console.error(`❌ Error creating envelope: ${error.response.status}`);
console.error(`Response: ${JSON.stringify(error.response.data, null, 2)}`);
} else {
console.error('❌ Error:', error.message);
}
throw error;
}
}
// Execute the function
createEnvelopeWithDocumentTemplate()
.then(bundle => {
console.log('Document template envelope creation completed');
})
.catch(error => {
console.error('Failed to create envelope');
});
Step 3: Create Envelope with Envelope Template
Envelope templates contain complete envelope configurations including documents, signers, and field assignments. They use a special endpoint and simpler request structure.
- Python
- JavaScript (Node.js)
import requests
import json
# Configuration
API_KEY = "your_api_key_here"
BASE_URL = "https://api.blueink.com/api/v2"
ENVELOPE_TEMPLATE_ID = "T-xxxxxxxxxxx" # Envelope template format
# Headers for authentication
headers = {
"Authorization": f"Token {API_KEY}",
"Content-Type": "application/json"
}
# Bundle request data using envelope template
bundle_request = {
"label": "Contract from Envelope Template",
"is_test": True, # Set to False for production
"packets": [
{
"key": "signer-1", # Must match template packet key
"name": "John Doe",
"email": "[email protected]"
}
],
"envelope_template": {
"template_id": ENVELOPE_TEMPLATE_ID,
"field_values": [ # Optional: Pre-fill template fields
{
"key": "company_name",
"initial_value": "ACME Corporation"
}
]
}
}
try:
# Create envelope using envelope template endpoint
response = requests.post(
f"{BASE_URL}/bundles/create_from_envelope_template/",
headers=headers,
json=bundle_request
)
if response.status_code == 201:
bundle = response.json()
print(f"✅ Envelope created from template successfully!")
print(f"Bundle ID: {bundle['id']}")
print(f"Status: {bundle['status']}")
print(f"📧 Envelope will be automatically sent to signers by background processes.")
print(f"View URL: https://app.blueink.com/bundles/{bundle['id']}")
else:
print(f"❌ Error creating envelope: {response.status_code}")
print(f"Response: {response.text}")
except Exception as e:
print(f"❌ Error: {e}")
const axios = require('axios');
// Configuration
const API_KEY = 'your_api_key_here';
const BASE_URL = 'https://api.blueink.com/api/v2';
const ENVELOPE_TEMPLATE_ID = 'T-xxxxxxxxxxx'; // Envelope template format
// Bundle request data using envelope template
const bundleRequest = {
label: 'Contract from Envelope Template',
is_test: true, // Set to false for production
packets: [
{
key: 'signer-1', // Must match template packet key
name: 'John Doe',
email: '[email protected]'
}
],
envelope_template: {
template_id: ENVELOPE_TEMPLATE_ID,
field_values: [ // Optional: Pre-fill template fields
{
key: 'company_name',
initial_value: 'ACME Corporation'
}
]
}
};
async function createEnvelopeWithEnvelopeTemplate() {
try {
const response = await axios.post(
`${BASE_URL}/bundles/create_from_envelope_template/`,
bundleRequest,
{
headers: {
'Authorization': `Token ${API_KEY}`,
'Content-Type': 'application/json'
}
}
);
if (response.status === 201) {
const bundle = response.data;
console.log('✅ Envelope created from template successfully!');
console.log(`Bundle ID: ${bundle.id}`);
console.log(`Status: ${bundle.status}`);
console.log('📧 Envelope will be automatically sent to signers by background processes.');
console.log(`View URL: https://app.blueink.com/bundles/${bundle.id}`);
return bundle;
}
} catch (error) {
if (error.response) {
console.error(`❌ Error creating envelope: ${error.response.status}`);
console.error(`Response: ${JSON.stringify(error.response.data, null, 2)}`);
} else {
console.error('❌ Error:', error.message);
}
throw error;
}
}
// Execute the function
createEnvelopeWithEnvelopeTemplate()
.then(bundle => {
console.log('Envelope template envelope creation completed');
})
.catch(error => {
console.error('Failed to create envelope');
});
API Response
When successful, both template methods return a 201 Created
status with the envelope details:
{
"id": "lL7g5Hn2Ni",
"created": "2025-09-04T23:18:57.615334Z",
"sent": null,
"completed_at": null,
"label": "Contract from Template",
"in_order": false,
"is_test": true,
"status": "pe",
"custom_key": null,
"custom_text": "",
"packets": [
{
"id": "a6v1qN4z8T",
"key": "signer-1",
"name": "John Doe",
"email": "[email protected]",
"phone": "",
"auth_sms": false,
"auth_selfie": false,
"auth_secrets": null,
"auth_id": false,
"person_id": "db600721-d8e7-42d3-8ebe-a180b4864eb8",
"status": "ne",
"deliver_via": "email",
"completed_at": null,
"last_accessed_at": null,
"order": 1,
"signing_complete_redirect": "",
"suppress_all": false,
"suppress_docs_ready": false,
"suppress_signing": false,
"suppress_reminder": false
}
],
"documents": [
{
"template_id": "your-template-uuid-here",
"key": "template-doc",
"name": "Contract Template"
}
],
"errors": null,
"cc_emails": [],
"email_message": "",
"email_subject": "",
"team": null,
"tags": [],
"send_reminders": false,
"reminder_offset": 0,
"reminder_interval": 0,
"reminder_expires": 0,
"expires": null,
"sms_message": "",
"requester_name": "",
"requester_email": "",
"payment": null
}
Status Codes Explained
- Bundle Status:
pe
= Pending (processing for automatic sending) - Packet Status:
ne
= Not sent yet (will be sent automatically) - Document Status: Shows template information
Envelope States:
pe
= Pending (default when created, will be automatically sent)dr
= Draft (add"status": "dr"
to bundle request to create as draft that won't be sent)se
= Sent (after background processing completes)
Envelopes are automatically sent by background processes after creation unless explicitly created as drafts.
Error Handling and Best Practices
Common Error Scenarios
-
Template Not Found (404 Not Found)
{
"detail": "Template matching template_id not found."
} -
Authentication Error (401 Unauthorized)
{
"detail": "Invalid token."
} -
Invalid Role Assignment (400 Bad Request)
{
"documents": [
{
"assignments": [
{
"role": ["Role 'invalid-role' not found in template."]
}
]
}
]
}
Best Practices
-
Template Management
- Keep template IDs in configuration files or environment variables
- Validate template availability before creating envelopes
- Use descriptive template names and maintain documentation
-
Role Assignments
- Ensure template roles match your assignment configurations
- Use consistent packet keys across your application
- Document role mappings for team members
-
Field Values
- Validate field keys exist in the template before setting values
- Consider using field values for personalization and pre-filling data
- Use field values to improve user experience by pre-populating known information
-
Error Handling
- Always check response status codes
- Log template-related errors for debugging
- Implement retry logic for transient failures
Template Types Comparison
Feature | Document Template | Envelope Template |
---|---|---|
Endpoint | /bundles/ | /bundles/create_from_envelope_template/ |
Template ID Format | UUID (e.g., 123e4567-e89b-12d3-a456-426614174000 ) | T-prefix (e.g., T-xxxxxxxxxxx ) |
Configuration | Documents only | Complete envelope setup |
Role Assignment | Required in request | Pre-configured in template |
Flexibility | High - mix with other documents | Medium - uses template structure |
Use Case | Reusable documents in various envelopes | Complete standardized workflows |
Complete Working Examples
Here are complete, production-ready examples that demonstrate both template types:
- Python
- JavaScript (Node.js)
#!/usr/bin/env python3
"""
Blueink Template Envelope Creator
Complete example for creating envelopes using both document and envelope templates
"""
import requests
import json
import sys
from typing import Optional, Dict, Any
class BlueinkTemplateEnvelopeCreator:
def __init__(self, api_key: str, base_url: str = "https://api.blueink.com/api/v2"):
self.api_key = api_key
self.base_url = base_url
self.headers = {
"Authorization": f"Token {api_key}",
"Content-Type": "application/json"
}
def create_envelope_with_document_template(
self,
template_id: str,
signer_name: str,
signer_email: str,
template_role: str,
label: str = "Document from Template",
is_test: bool = True,
field_values: Optional[list] = None
) -> Optional[Dict[Any, Any]]:
"""Create envelope using a document template"""
# Prepare bundle request
bundle_request = {
"label": label,
"is_test": is_test,
"packets": [
{
"key": "signer-1",
"name": signer_name,
"email": signer_email,
"deliver_via": "email"
}
],
"documents": [
{
"key": "template-doc",
"template_id": template_id,
"assignments": [
{
"role": template_role,
"signer": "signer-1"
}
]
}
]
}
# Add field values if provided
if field_values:
bundle_request["documents"][0]["field_values"] = field_values
try:
response = requests.post(
f"{self.base_url}/bundles/",
headers=self.headers,
json=bundle_request,
timeout=30
)
if response.status_code == 201:
bundle = response.json()
print(f"✅ Document template envelope created successfully!")
print(f" Bundle ID: {bundle['id']}")
print(f" Status: {bundle['status']}")
print(f" Template ID: {template_id}")
return bundle
else:
print(f"❌ Error creating envelope: {response.status_code}")
print(f" Response: {response.text}")
return None
except requests.exceptions.RequestException as e:
print(f"❌ Request failed: {e}")
return None
def create_envelope_with_envelope_template(
self,
template_id: str,
signer_name: str,
signer_email: str,
signer_key: str,
label: str = "Envelope from Template",
is_test: bool = True,
field_values: Optional[list] = None
) -> Optional[Dict[Any, Any]]:
"""Create envelope using an envelope template"""
# Prepare bundle request
bundle_request = {
"label": label,
"is_test": is_test,
"packets": [
{
"key": signer_key, # Must match template packet key
"name": signer_name,
"email": signer_email
}
],
"envelope_template": {
"template_id": template_id
}
}
# Add field values if provided
if field_values:
bundle_request["envelope_template"]["field_values"] = field_values
try:
response = requests.post(
f"{self.base_url}/bundles/create_from_envelope_template/",
headers=self.headers,
json=bundle_request,
timeout=30
)
if response.status_code == 201:
bundle = response.json()
print(f"✅ Envelope template envelope created successfully!")
print(f" Bundle ID: {bundle['id']}")
print(f" Status: {bundle['status']}")
print(f" Template ID: {template_id}")
return bundle
else:
print(f"❌ Error creating envelope: {response.status_code}")
print(f" Response: {response.text}")
return None
except requests.exceptions.RequestException as e:
print(f"❌ Request failed: {e}")
return None
def main():
# Configuration
API_KEY = "your_api_key_here"
SIGNER_NAME = "John Doe"
SIGNER_EMAIL = "[email protected]"
# Template IDs (replace with your actual template IDs)
DOCUMENT_TEMPLATE_ID = "your-document-template-uuid"
ENVELOPE_TEMPLATE_ID = "T-your-envelope-template-id"
# Create envelope creator instance
creator = BlueinkTemplateEnvelopeCreator(API_KEY)
try:
print("🔄 Creating envelope with document template...")
doc_bundle = creator.create_envelope_with_document_template(
template_id=DOCUMENT_TEMPLATE_ID,
signer_name=SIGNER_NAME,
signer_email=SIGNER_EMAIL,
template_role="customer", # Replace with your template role
label="Contract from Document Template",
is_test=True,
field_values=[
{
"key": "company_name",
"initial_value": "ACME Corporation"
}
]
)
print("\n🔄 Creating envelope with envelope template...")
env_bundle = creator.create_envelope_with_envelope_template(
template_id=ENVELOPE_TEMPLATE_ID,
signer_name=SIGNER_NAME,
signer_email=SIGNER_EMAIL,
signer_key="signer-1", # Replace with your template packet key
label="Contract from Envelope Template",
is_test=True,
field_values=[
{
"key": "company_name",
"initial_value": "ACME Corporation"
}
]
)
if doc_bundle or env_bundle:
print("\n📧 Envelopes will be automatically sent to signers by background processes.")
except Exception as e:
print(f"❌ Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env node
/**
* Blueink Template Envelope Creator
* Complete example for creating envelopes using both document and envelope templates
*/
const axios = require('axios');
class BlueinkTemplateEnvelopeCreator {
constructor(apiKey, baseUrl = 'https://api.blueink.com/api/v2') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
this.headers = {
'Authorization': `Token ${apiKey}`,
'Content-Type': 'application/json'
};
}
async createEnvelopeWithDocumentTemplate(
templateId,
signerName,
signerEmail,
templateRole,
label = 'Document from Template',
isTest = true,
fieldValues = null
) {
// Prepare bundle request
const bundleRequest = {
label: label,
is_test: isTest,
packets: [
{
key: 'signer-1',
name: signerName,
email: signerEmail,
deliver_via: 'email'
}
],
documents: [
{
key: 'template-doc',
template_id: templateId,
assignments: [
{
role: templateRole,
signer: 'signer-1'
}
]
}
]
};
// Add field values if provided
if (fieldValues) {
bundleRequest.documents[0].field_values = fieldValues;
}
try {
const response = await axios.post(
`${this.baseUrl}/bundles/`,
bundleRequest,
{
headers: this.headers,
timeout: 30000
}
);
if (response.status === 201) {
const bundle = response.data;
console.log('✅ Document template envelope created successfully!');
console.log(` Bundle ID: ${bundle.id}`);
console.log(` Status: ${bundle.status}`);
console.log(` Template ID: ${templateId}`);
return bundle;
}
} catch (error) {
if (error.response) {
console.error(`❌ Error creating envelope: ${error.response.status}`);
console.error(` Response: ${JSON.stringify(error.response.data, null, 2)}`);
} else {
console.error(`❌ Request failed: ${error.message}`);
}
throw error;
}
}
async createEnvelopeWithEnvelopeTemplate(
templateId,
signerName,
signerEmail,
signerKey,
label = 'Envelope from Template',
isTest = true,
fieldValues = null
) {
// Prepare bundle request
const bundleRequest = {
label: label,
is_test: isTest,
packets: [
{
key: signerKey, // Must match template packet key
name: signerName,
email: signerEmail
}
],
envelope_template: {
template_id: templateId
}
};
// Add field values if provided
if (fieldValues) {
bundleRequest.envelope_template.field_values = fieldValues;
}
try {
const response = await axios.post(
`${this.baseUrl}/bundles/create_from_envelope_template/`,
bundleRequest,
{
headers: this.headers,
timeout: 30000
}
);
if (response.status === 201) {
const bundle = response.data;
console.log('✅ Envelope template envelope created successfully!');
console.log(` Bundle ID: ${bundle.id}`);
console.log(` Status: ${bundle.status}`);
console.log(` Template ID: ${templateId}`);
return bundle;
}
} catch (error) {
if (error.response) {
console.error(`❌ Error creating envelope: ${error.response.status}`);
console.error(` Response: ${JSON.stringify(error.response.data, null, 2)}`);
} else {
console.error(`❌ Request failed: ${error.message}`);
}
throw error;
}
}
}
async function main() {
// Configuration
const API_KEY = 'your_api_key_here';
const SIGNER_NAME = 'John Doe';
const SIGNER_EMAIL = '[email protected]';
// Template IDs (replace with your actual template IDs)
const DOCUMENT_TEMPLATE_ID = 'your-document-template-uuid';
const ENVELOPE_TEMPLATE_ID = 'T-your-envelope-template-id';
// Create envelope creator instance
const creator = new BlueinkTemplateEnvelopeCreator(API_KEY);
try {
console.log('🔄 Creating envelope with document template...');
const docBundle = await creator.createEnvelopeWithDocumentTemplate(
DOCUMENT_TEMPLATE_ID,
SIGNER_NAME,
SIGNER_EMAIL,
'customer', // Replace with your template role
'Contract from Document Template',
true,
[
{
key: 'company_name',
initial_value: 'ACME Corporation'
}
]
);
console.log('\n🔄 Creating envelope with envelope template...');
const envBundle = await creator.createEnvelopeWithEnvelopeTemplate(
ENVELOPE_TEMPLATE_ID,
SIGNER_NAME,
SIGNER_EMAIL,
'signer-1', // Replace with your template packet key
'Contract from Envelope Template',
true,
[
{
key: 'company_name',
initial_value: 'ACME Corporation'
}
]
);
if (docBundle || envBundle) {
console.log('\n📧 Envelopes will be automatically sent to signers by background processes.');
}
} catch (error) {
console.error(`❌ Unexpected error: ${error.message}`);
process.exit(1);
}
}
// Run the script
if (require.main === module) {
main().catch(error => {
console.error('Script failed:', error.message);
process.exit(1);
});
}
module.exports = { BlueinkTemplateEnvelopeCreator };
Next Steps
Now that you've learned how to create envelopes using templates, you might want to explore:
- Send Envelope with Uploaded PDF - How to create envelopes by uploading PDF files
- Auto Placement - How to automatically place fields next to specified strings in documents
- API Reference - Complete API documentation for all endpoints and operations
- Quick Start Guide - Get started with the BlueInk API basics
Need Help?
If you encounter issues or have questions:
- Check the API Reference for detailed endpoint documentation
- Visit our Support Center for additional resources
- Contact our support team through the BlueInk Dashboard
Templates provide a powerful way to standardize your document workflows and reduce the complexity of envelope creation. By pre-configuring documents and envelope structures, you can ensure consistency while simplifying your integration code.