Contract Creation Guide
APISign supports two distinct workflows for creating contracts, each suited for different use cases. This guide explains both approaches and when to use each one.
Overview
Two Contract Creation Flows
- Blank Contract (One-off) - Start from scratch with custom content and fields
- Template-based Contract - Use a pre-defined template with variable substitution
Important Validation Rules
Template-Based Contracts:
- Must provide
template_idto identify the template - Must provide
variablesobject with values for all creator-completed fields from the template - Must NOT provide
content(content comes from the template) - Must NOT provide
fields(field definitions come from the template)
Non-Template (Blank) Contracts:
- Must provide
contentwith the full contract markdown - Must provide
fieldsarray defining all field types and assignments - Must NOT provide
template_id - Must NOT provide
variables(use fields directly in the content)
Flow 1: Blank Contract Creation
When to Use
- One-time contracts with unique terms
- Quick agreements without needing reusability
- Custom contracts that don't fit existing templates
- Situations where field types and assignments are known upfront
How It Works
- Provide the complete contract content in markdown format
- Define field types and assignments directly in the creation request
- Send immediately to signers
API Endpoint
POST /api/contract/create
Request Format
{
"name": "Service Agreement - John Smith",
"content": "# Service Agreement\n\nThis agreement is between {{COMPANY_NAME}} and {{CLIENT_NAME}}.\n\n**Service Type:** {{SERVICE_CATEGORY}}\n**Project:** {{PROJECT_DESCRIPTION}}\n\nSigned on {{DATE_SIGNED}}\n\n{{CLIENT_SIGNATURE}}\n{{CLIENT_INITIALS}}",
"fields": [
{
"name": "COMPANY_NAME",
"type": "text",
"completedBy": "creator"
},
{
"name": "CLIENT_NAME",
"type": "text",
"completedBy": "creator"
},
{
"name": "SERVICE_CATEGORY",
"type": "label",
"completedBy": "creator"
},
{
"name": "PROJECT_DESCRIPTION",
"type": "text",
"completedBy": "creator"
},
{
"name": "DATE_SIGNED",
"type": "date",
"completedBy": "signer"
},
{
"name": "CLIENT_SIGNATURE",
"type": "signature",
"completedBy": "signer"
},
{
"name": "CLIENT_INITIALS",
"type": "initials",
"completedBy": "signer"
}
],
"signers": [
{
"name": "John Smith",
"email": "john@example.com",
"signing_order": 1
}
],
}
Field Types
text- Plain text input for general data entryemail- Email address input with validationphone- Phone number input with formattingdate- Date picker for selecting dateslabel- Display-only text label (non-editable, useful for categories/descriptions)signature- Signature drawing canvas for legal signaturesinitials- Initials drawing canvas for acknowledgmentstimestamp- Auto-filled with signing timestampsigner_name- Auto-filled with signer's name
Field Assignment
creator- Filled when creating the contractsigner- Filled by the signer during signing process
Flow 2: Template-based Contract Creation
When to Use
- Recurring contracts with standard terms
- Contracts that follow organizational templates
- High-volume contract generation
- Situations requiring consistency across multiple contracts
How It Works
- Create a reusable template with variables
- Create contracts from the template
- Provide values for creator variables
- System handles field types and signer assignments from template
Step 1: Create Template
POST /api/template/create
{
"name": "Service Agreement Template",
"content": "# Service Agreement\n\nThis agreement is between {{COMPANY_NAME}} and {{CLIENT_NAME}}...\n\nService starts: {{START_DATE}}\nService ends: {{END_DATE}}\n\nRate: {{HOURLY_RATE}}/hour\n\nSigned on {{DATE_SIGNED}}\n\n{{CLIENT_SIGNATURE}}\n{{CLIENT_INITIALS}}",
"fields": [
{
"name": "COMPANY_NAME",
"type": "text",
"completedBy": "creator"
},
{
"name": "CLIENT_NAME",
"type": "text",
"completedBy": "creator"
},
{
"name": "START_DATE",
"type": "date",
"completedBy": "creator"
},
{
"name": "END_DATE",
"type": "date",
"completedBy": "creator"
},
{
"name": "HOURLY_RATE",
"type": "text",
"completedBy": "creator"
},
{
"name": "DATE_SIGNED",
"type": "date",
"completedBy": "signer"
},
{
"name": "CLIENT_SIGNATURE",
"type": "signature",
"completedBy": "signer"
},
{
"name": "CLIENT_INITIALS",
"type": "initials",
"completedBy": "signer"
}
]
}
Step 2: Create Contract from Template
POST /api/contract/create
{
"name": "Service Agreement - John Smith",
"template_id": "cm4abc123...",
"signers": [
{
"name": "John Smith",
"email": "john@example.com",
"signing_order": 1
}
],
"variables": {
"COMPANY_NAME": "Acme Corp",
"CLIENT_NAME": "John Smith",
"START_DATE": "2024-01-01",
"END_DATE": "2024-12-31",
"HOURLY_RATE": "$150"
},
}
Key Differences
| Aspect | Blank Contract | Template-based |
|---|---|---|
| Content Source | Provided in request (required) | From template (must not provide) |
| Field Definitions | Provided in request (required) | Inherited from template (must not provide) |
| Variables | Not used (must not provide) | Required for creator fields |
| Reusability | One-time use | Reusable template |
| Setup Time | Quick for one-off | Initial template setup required |
| Consistency | Manual consistency | Enforced by template |
| Best For | Unique agreements | Standardized contracts |
| Variable Substitution | At signing time | Creator values at creation, signer values at signing |
Variable Processing
Creator Variables (Template Contracts Only)
- Substituted when the contract is created
- Values provided in
variablesobject - Permanently replaced in the contract content
- Not visible to signers
- All creator-completed fields from the template must have values provided
Signer Variables
- Remain as placeholders until signing
- Each signer only sees and fills their assigned fields
- Different signers can have different field assignments
- Auto-filled fields (timestamp, signer_name) populate automatically
Multi-signer Support
Both flows support multiple signers with ordered signing:
{
"signers": [
{
"name": "First Signer",
"email": "first@example.com",
"signing_order": 1
},
{
"name": "Second Signer",
"email": "second@example.com",
"signing_order": 2
}
],
"fields": {
"signers": [
{
"signing_order": 1,
"signerFields": ["FIELD1", "SIGNATURE1"]
},
{
"signing_order": 2,
"signerFields": ["FIELD2", "SIGNATURE2"]
}
]
}
}
Response Format
Both flows return the same response structure:
{
"contract": {
"id": "cm4xyz789...",
"name": "Service Agreement - John Smith",
"status": "sent",
"created_at": "2024-01-15T10:00:00Z",
"sent_at": "2024-01-15T10:00:01Z"
},
"signers": [
{
"id": "cm4signer1...",
"name": "John Smith",
"email": "john@example.com",
"status": "pending",
"signing_order": 1,
"signing_url": "https://app.apisign.io/sign?contract=cm4xyz789&signer=cm4signer1"
}
]
}
Error Handling
Common errors and their meanings:
400 Bad Request- Invalid field definitions or missing required data404 Not Found- Template not found (for template-based creation)422 Unprocessable Entity- Variable mismatch or invalid field assignments
Best Practices
For Blank Contracts
- Define all fields upfront to ensure proper rendering
- Test the markdown formatting before sending
- Validate email addresses before creation
- Use descriptive field names
For Template-based Contracts
- Create templates for frequently used contract types
- Use consistent variable naming conventions
- Document required creator_values for each template
- Version templates when making significant changes
- Test templates thoroughly before production use
Examples
Example 1: Simple NDA (Blank Contract)
{
"name": "NDA - Quick Agreement",
"content": "# Non-Disclosure Agreement\n\nEffective {{DATE}}\n\nParties agree to maintain confidentiality...\n\n{{SIGNATURE}}",
"fields": [
{
"name": "DATE",
"type": "date",
"completedBy": "signer"
},
{
"name": "SIGNATURE",
"type": "signature",
"completedBy": "signer"
}
],
"signers": [
{
"name": "Jane Doe",
"email": "jane@example.com",
"signing_order": 1
}
]
}
Example 2: Employment Contract (Template-based)
First create the template, then create contracts from it with different employee details:
{
"template_id": "cm4empl001...",
"name": "Employment Contract - Sarah Johnson",
"signers": [
{
"name": "Sarah Johnson",
"email": "sarah@example.com",
"signing_order": 1
}
],
"creator_values": {
"EMPLOYEE_NAME": "Sarah Johnson",
"POSITION": "Senior Developer",
"SALARY": "$120,000",
"START_DATE": "2024-02-01",
"DEPARTMENT": "Engineering"
},
}