Skip to main content

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:

  1. Document Templates - Pre-configured documents with fields that can be reused across multiple envelopes
  2. 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
tip

If you don't have an API key yet, visit the Authentication guide to learn how to obtain one.

Test Mode Email Restrictions

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.

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}")

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.

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}")

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
info

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

  1. Template Not Found (404 Not Found)

    {
    "detail": "Template matching template_id not found."
    }
  2. Authentication Error (401 Unauthorized)

    {
    "detail": "Invalid token."
    }
  3. Invalid Role Assignment (400 Bad Request)

    {
    "documents": [
    {
    "assignments": [
    {
    "role": ["Role 'invalid-role' not found in template."]
    }
    ]
    }
    ]
    }

Best Practices

  1. Template Management

    • Keep template IDs in configuration files or environment variables
    • Validate template availability before creating envelopes
    • Use descriptive template names and maintain documentation
  2. Role Assignments

    • Ensure template roles match your assignment configurations
    • Use consistent packet keys across your application
    • Document role mappings for team members
  3. 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
  4. Error Handling

    • Always check response status codes
    • Log template-related errors for debugging
    • Implement retry logic for transient failures

Template Types Comparison

FeatureDocument TemplateEnvelope Template
Endpoint/bundles//bundles/create_from_envelope_template/
Template ID FormatUUID (e.g., 123e4567-e89b-12d3-a456-426614174000)T-prefix (e.g., T-xxxxxxxxxxx)
ConfigurationDocuments onlyComplete envelope setup
Role AssignmentRequired in requestPre-configured in template
FlexibilityHigh - mix with other documentsMedium - uses template structure
Use CaseReusable documents in various envelopesComplete standardized workflows

Complete Working Examples

Here are complete, production-ready examples that demonstrate both template types:

#!/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()

Next Steps

Now that you've learned how to create envelopes using templates, you might want to explore:

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.