Create a Basic Template via API
A Template is the detailed blueprint for a single document within SignStack. It defines the base PDF document, the interactive fields overlaid on it, and the participant roles and required data (entity slots). It specifies what the document contains and needs but does not define the workflow steps (that's the job of a Blueprint). This guide shows how to create your first basic Template using the API.
Think of creating a Template like designing a reusable form – you define the background PDF and where the blanks go.
Understanding Field Values: The SignStack Difference (Decoupling via Entities)
Before defining the template, it's crucial to understand how SignStack handles field values differently from many systems. Instead of your application code needing to know specific field keys to push values, fields in SignStack pull their values from the workflow's central Entity data using expressions.
-
Work with Your Business Objects (
Entities): SignStack revolves around the canonicalEntitiesthat represent your core business data (likeclientInfo,dealInfo). These align directly with the business objects you already use in your own backend. Your application code primarily interacts with these familiar structures. -
Declare Data Needs (
entitySlots): YourTemplatedeclares theEntitiesit needs using theentitySlotsarray. This defines the "data contract.""entitySlots": [ { "key": "employeeInfo", "schemaKey": "employeeSchemaV1", ... }, { "key": "offerDetails", "schemaKey": "offerSchemaV1", ... } ] -
Template Logic Pulls from Entities (
valueExpression): Eachfieldon the template uses a JSONata expression (valueExpression) to define how it should calculate its value based on the data available in theEntityContext. The template, not your application code, owns this presentation logic.// Template field knows how to get the name from the 'employeeInfo' entity "valueExpression": "entities.employeeInfo.firstName & ' ' & entities.employeeInfo.lastName" -
Application Code Stays Clean: Your backend application code doesn't need to know about specific field keys like
employeeNameFieldorsalaryField. Its only job is to provide the requiredemployeeInfoandofferDetailsEntityobjects that conform to the specified schema when starting theWorkflow.
The Benefit: True Decoupling & Centralized Logic. This approach completely decouples your backend application logic from the presentation details of your templates. The Entities act as the clean interface between your system and SignStack. All presentation logic (valueExpression, displayCondition) lives within the Template, centralizing your document-related rules within SignStack and keeping your application code focused on core business logic. This makes both your application and your templates easier to manage, evolve, and audit.
Prerequisites
Before creating a Template, you first need to upload the base PDF document to SignStack and get its unique fileId.
-
Upload your Base PDF: Use the File Management API (
POST /files/initiate-upload, upload the file) to upload your base document (e.g.,Offer_Letter.pdf). Make sure to calculate and include thecontentHash. -
Store the
fileId: Keep the returnedfileIdhandy; you'll need it when defining the template.
(See Core Concepts: File Management for details on file uploads.)
1. Define the Template JSON
Now, construct the full JSON payload for your Template. This includes defining its manifest (roles, entitySlots) and its fields.
Example template_payload.json:
{
"key": "simpleOfferLetter", // Unique camelCase key for this template family
"displayName": "Simple Offer Letter Template",
"version": "1.0.0", // First version is always 1.0.0
"status": "Draft", // Start as Draft
"templateFormat": "PDF", // Specify PDF format
"fileId": "file_abc123xyz...", // The fileId obtained in prerequisites
"roles": [ // Declare participant roles needed
{ "key": "newHire", "displayName": "New Hire", "roleCategory": "Signer", "isMandatory": true },
{ "key": "hrManager", "displayName": "HR Manager", "roleCategory": "Signer", "isMandatory": true }
],
"entitySlots": [ // Declare data entities needed
{
"key": "offerDetails", // Local key/variable name for this entity
"displayName": "Offer Details",
"schemaKey": "offerSchemaV1", // Link to the schema definition
"compatibleSchemaVersion": "^1.0.0",
"isMandatory": true
},
{
"key": "employeeInfo",
"displayName": "Employee Info",
"schemaKey": "employeeSchemaV1",
"compatibleSchemaVersion": "^1.0.0",
"isMandatory": true
}
],
"fields": [ // Define the interactive fields
{
"key": "employeeNameDisplay",
"type": "Text",
"valueExpression": "entities.employeeInfo.firstName & ' ' & entities.employeeInfo.lastName",
"widgets": [ /* Position info */ ]
},
{
"key": "employeeEmailReview",
"type": "Text",
"assignedToRoleKey": "newHire",
"valueExpression": "entities.employeeInfo.email", // Gets initial value
"widgets": [ /* Position info */ ]
},
{
"key": "bonusAmountField", // Example field using displayCondition
"type": "Text",
"assignedToRoleKey": "hrManager", // HR enters bonus if applicable
// Only show this field if the 'baseSalary' in offerDetails is above 120000
"displayCondition": "entities.offerDetails.baseSalary > 120000",
"widgets": [ /* Position info */ ]
},
{
"key": "employeeSignature",
"type": "Signature",
"assignedToRoleKey": "newHire",
"widgets": [ /* Position info */ ]
},
{
"key": "hrSignature",
"type": "Signature",
"assignedToRoleKey": "hrManager",
"widgets": [ /* Position info */ ]
}
]
}
-
Manifest: Defines the
rolesandentitySlotsthis template requires. -
fileId: Links to the base PDF you uploaded. -
fields: Defines each interactive element.-
assignedToRoleKeyis optional (usually used for interactive fields). -
valueExpressiondefines how the field calculates its initial value fromEntities. -
displayConditionis an optional JSONata expression that controls field visibility. It's evaluated against theEntityContext– iftrue, the field is shown; otherwise, it's hidden. -
widgetsdefine the field's position and appearance.
-
(Note: Refer to the API Reference for the full schema details.)
2. Create the Template via API
Save the JSON structure above into a file (e.g., template_payload.json) and then create the Template using the API.
-
Endpoint:
POST /v1/organizations/{organizationId}/templates -
Authentication: Requires a valid SignStack JWT Access Token.
Example curl Request:
curl -X POST \
[https://api.signstack.com/v1/organizations/me/templates](https://api.signstack.com/v1/organizations/me/templates) \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
--data @template_payload.json
3. Success Response
If successful, the API will return a 201 Created status and the full object for the newly created Template version (v1.0.0 with status: "Draft").
Example Response (truncated):
{
"id": "tpl_123abc456def",
"organizationId": "org_...",
"key": "simpleOfferLetter",
"displayName": "Simple Offer Letter Template",
"version": "1.0.0",
"status": "Draft",
// ... other properties ...
"createdAt": "...",
"updatedAt": "..."
}
You have now created your first Template via the API, defining its structure and data-driven logic! This template can now be referenced by its key (simpleOfferLetter) when designing Blueprints or creating Workflows. Remember to update its status from Draft to Active when it's ready for use.
➡️ Next: Guides: Making Fields Dynamic with Expressions