# 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](/docs/esignature-api/authentication/) 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.

#### Python

### Using the Python SDK

```python
from blueink.client import Client

client = Client(api_key="your_api_key_here")

# Bundle data using document template
bundle_data = {
    "label": "Contract from Template",
    "is_test": True,
    "packets": [
        {
            "key": "signer-1",
            "name": "John Doe",
            "email": "john.doe@example.com",
            "deliver_via": "email"
        }
    ],
    "documents": [
        {
            "key": "template-doc",
            "template_id": "your-template-uuid-here",
            "assignments": [
                {
                    "role": "customer",
                    "signer": "signer-1"
                }
            ]
        }
    ]
}

response = client.bundles.create(data=bundle_data)
if response.status == 201:
    print(f"✅ Envelope created successfully! Bundle ID: {response.data.id}")
```

#### JavaScript

### Using the JavaScript SDK

```javascript
const { Client } = require('@blueink360/blueink-client-js');
const client = new Client('your_api_key_here');

const bundleData = {
    label: 'Contract from Template',
    is_test: true,
    packets: [
        {
            key: 'signer-1',
            name: 'John Doe',
            email: 'john.doe@example.com',
            deliver_via: 'email'
        }
    ],
    documents: [
        {
            key: 'template-doc',
            template_id: 'your-template-uuid-here',
            assignments: [
                {
                    role: 'customer',
                    signer: 'signer-1'
                }
            ]
        }
    ]
};

client.bundles.create(bundleData)
    .then(response => {
        console.log(`✅ Envelope created successfully! Bundle ID: ${response.data.id}`);
    });
```

#### PHP

### Using the PHP SDK

```php
<?php
use Blueink\ClientSDK\Client;

$client = new Client("your_api_key_here");

$bundleData = [
    "label" => "Contract from Template",
    "is_test" => true,
    "packets" => [
        [
            "key" => "signer-1",
            "name" => "John Doe",
            "email" => "john.doe@example.com",
            "deliver_via" => "email"
        ]
    ],
    "documents" => [
        [
            "key" => "template-doc",
            "template_id" => "your-template-uuid-here",
            "assignments" => [
                [
                    "role" => "customer",
                    "signer" => "signer-1"
                ]
            ]
        ]
    ]
];

$response = $client->bundles->create($bundleData);

if ($response->status === 201) {
    echo "✅ Envelope created successfully! Bundle ID: " . $response->data->id;
}
```

## 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

### Using the Python SDK

```python
from blueink.client import Client

client = Client(api_key="your_api_key_here")

# Bundle request data using envelope template
bundle_data = {
    "label": "Contract from Envelope Template",
    "is_test": True,
    "packets": [
        {
            "key": "signer-1",  # Must match template packet key
            "name": "John Doe",
            "email": "john.doe@example.com"
        }
    ],
    "envelope_template": {
        "template_id": "T-xxxxxxxxxxx"
    }
}

response = client.bundles.create_from_envelope_template(data=bundle_data)

if response.status == 201:
    print(f"✅ Envelope created from template successfully! Bundle ID: {response.data.id}")
```

#### JavaScript

### Using the JavaScript SDK

```javascript
const { Client } = require('@blueink360/blueink-client-js');
const client = new Client('your_api_key_here');

const bundleData = {
    label: 'Contract from Envelope Template',
    is_test: true,
    packets: [
        {
            key: 'signer-1', // Must match template packet key
            name: 'John Doe',
            email: 'john.doe@example.com'
        }
    ],
    envelope_template: {
        template_id: 'T-xxxxxxxxxxx'
    }
};

client.bundles.create_from_envelope_template(bundleData)
    .then(response => {
        console.log(`✅ Envelope created successfully! Bundle ID: ${response.data.id}`);
    });
```

#### PHP

### Using the PHP SDK

```php
<?php
use Blueink\ClientSDK\Client;

$client = new Client("your_api_key_here");

$bundleData = [
    "label" => "Contract from Envelope Template",
    "is_test" => true,
    "packets" => [
        [
            "key" => "signer-1", // Must match template packet key
            "name" => "John Doe",
            "email" => "john.doe@example.com"
        ]
    ],
    "envelope_template" => [
        "template_id" => "T-xxxxxxxxxxx"
    ]
];

$response = $client->bundles->create_from_envelope_template($bundleData);

if ($response->status === 201) {
    echo "✅ Envelope created from template successfully! Bundle ID: " . $response->data->id;
}
```

## API Response

When successful, both template methods return a `201 Created` status with the envelope details:

```json
{
    "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": "john.doe@example.com",
            "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)**
   ```json
   {
       "detail": "Template matching template_id not found."
   }
   ```

2. **Authentication Error (401 Unauthorized)**
   ```json
   {
       "detail": "Invalid token."
   }
   ```

3. **Invalid Role Assignment (400 Bad Request)**
   ```json
   {
       "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

| 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

```python
#!/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 = "john.doe@example.com"

    # 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()
```

#### JavaScript (Node.js)

```javascript
#!/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 = 'john.doe@example.com';

    // 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](/docs/guides/send-envelope-with-uploaded-pdf/)** - How to create envelopes by uploading PDF files
- **[Auto Placement](/docs/guides/auto-placement/)** - How to automatically place fields next to specified strings in documents
- **[API Reference](/docs/api/)** - Complete API documentation for all endpoints and operations
- **[Quick Start Guide](/docs/quick-start/)** - Get started with the BlueInk API basics

## Need Help?

If you encounter issues or have questions:

- Check the [API Reference](/docs/api/) for detailed endpoint documentation
- Visit our [Support Center](https://help.blueink.com) 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.
