import { FirmaClient } from "@firma-dev/sdk";
const firma = new FirmaClient({ apiKey: "YOUR_API_KEY" });
const response = await firma.templates.createTemplate({
name: "Employment Contract Template",
document: "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c..."
});
console.log(response);curl --request POST \
--url https://api.firma.dev/functions/v1/signing-request-api/templates \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Employment Contract Template",
"document": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...",
"description": "Standard employment contract for new hires",
"expiration_hours": 168,
"settings": {
"allow_editing_before_sending": false,
"attach_pdf_on_finish": true,
"allow_download": true,
"hand_drawn_only": false,
"require_otp_verification": null,
"disable_guided_navigation": true,
"allow_presigning_download": true,
"show_qr_code": true
},
"document_id": "123e4567-e89b-12d3-a456-426614174000"
}
'import requests
url = "https://api.firma.dev/functions/v1/signing-request-api/templates"
payload = {
"name": "Employment Contract Template",
"document": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...",
"description": "Standard employment contract for new hires",
"expiration_hours": 168,
"settings": {
"allow_editing_before_sending": False,
"attach_pdf_on_finish": True,
"allow_download": True,
"hand_drawn_only": False,
"require_otp_verification": None,
"disable_guided_navigation": True,
"allow_presigning_download": True,
"show_qr_code": True
},
"document_id": "123e4567-e89b-12d3-a456-426614174000"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Employment Contract Template',
document: 'JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...',
description: 'Standard employment contract for new hires',
expiration_hours: 168,
settings: {
allow_editing_before_sending: false,
attach_pdf_on_finish: true,
allow_download: true,
hand_drawn_only: false,
require_otp_verification: null,
disable_guided_navigation: true,
allow_presigning_download: true,
show_qr_code: true
},
document_id: '123e4567-e89b-12d3-a456-426614174000'
})
};
fetch('https://api.firma.dev/functions/v1/signing-request-api/templates', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.firma.dev/functions/v1/signing-request-api/templates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Employment Contract Template',
'document' => 'JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...',
'description' => 'Standard employment contract for new hires',
'expiration_hours' => 168,
'settings' => [
'allow_editing_before_sending' => false,
'attach_pdf_on_finish' => true,
'allow_download' => true,
'hand_drawn_only' => false,
'require_otp_verification' => null,
'disable_guided_navigation' => true,
'allow_presigning_download' => true,
'show_qr_code' => true
],
'document_id' => '123e4567-e89b-12d3-a456-426614174000'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.firma.dev/functions/v1/signing-request-api/templates"
payload := strings.NewReader("{\n \"name\": \"Employment Contract Template\",\n \"document\": \"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...\",\n \"description\": \"Standard employment contract for new hires\",\n \"expiration_hours\": 168,\n \"settings\": {\n \"allow_editing_before_sending\": false,\n \"attach_pdf_on_finish\": true,\n \"allow_download\": true,\n \"hand_drawn_only\": false,\n \"require_otp_verification\": null,\n \"disable_guided_navigation\": true,\n \"allow_presigning_download\": true,\n \"show_qr_code\": true\n },\n \"document_id\": \"123e4567-e89b-12d3-a456-426614174000\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.firma.dev/functions/v1/signing-request-api/templates")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Employment Contract Template\",\n \"document\": \"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...\",\n \"description\": \"Standard employment contract for new hires\",\n \"expiration_hours\": 168,\n \"settings\": {\n \"allow_editing_before_sending\": false,\n \"attach_pdf_on_finish\": true,\n \"allow_download\": true,\n \"hand_drawn_only\": false,\n \"require_otp_verification\": null,\n \"disable_guided_navigation\": true,\n \"allow_presigning_download\": true,\n \"show_qr_code\": true\n },\n \"document_id\": \"123e4567-e89b-12d3-a456-426614174000\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.firma.dev/functions/v1/signing-request-api/templates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Employment Contract Template\",\n \"document\": \"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...\",\n \"description\": \"Standard employment contract for new hires\",\n \"expiration_hours\": 168,\n \"settings\": {\n \"allow_editing_before_sending\": false,\n \"attach_pdf_on_finish\": true,\n \"allow_download\": true,\n \"hand_drawn_only\": false,\n \"require_otp_verification\": null,\n \"disable_guided_navigation\": true,\n \"allow_presigning_download\": true,\n \"show_qr_code\": true\n },\n \"document_id\": \"123e4567-e89b-12d3-a456-426614174000\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"created_date": "2023-11-07T05:31:56Z",
"description": "<string>",
"document_url": "<string>",
"document_url_expires_at": "2023-11-07T05:31:56Z",
"page_count": 2,
"expiration_hours": 168,
"credit_cost": 1,
"settings": {
"allow_download": true,
"attach_pdf_on_finish": true,
"allow_editing_before_sending": false,
"use_signing_order": true,
"hand_drawn_only": false,
"send_signing_email": true,
"send_finish_email": true,
"send_expiration_email": true,
"send_cancellation_email": true,
"require_otp_verification": null,
"disable_guided_navigation": true,
"allow_presigning_download": true,
"show_qr_code": true,
"identity_editable_fields": [
"<string>"
],
"notify_identity_change_email": false
},
"recipients": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"email": "jsmith@example.com",
"first_name": "<string>",
"order": 2,
"name": "<string>",
"last_name": "<string>",
"phone_number": "<string>",
"street_address": "<string>",
"city": "<string>",
"state_province": "<string>",
"postal_code": "<string>",
"country": "<string>",
"title": "<string>",
"company": "<string>",
"required_fields": [
"<string>"
],
"missing_fields": [
"<string>"
],
"required_read_only_fields": [
{
"variable_name": "<string>",
"variable_defined_name": "<string>",
"field_type": "<string>"
}
],
"ready_to_send": true
}
],
"fields": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"page_number": 2,
"required": true,
"recipient_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"variable_name": "<string>",
"variable_defined_name": "<string>",
"position": {
"x": 50,
"y": 50,
"width": 50,
"height": 50
},
"dropdown_options": [
"<string>"
],
"multi_group_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"date_default": "2023-12-25",
"date_signing_default": true,
"format_rules": {
"dateFormat": "MMMM dd, yyyy"
},
"validation_rules": {},
"read_only": false,
"read_only_value": "<string>"
}
],
"updated_date": "2023-11-07T05:31:56Z"
}{
"error": "Validation Error",
"message": "Invalid input data",
"details": {
"name": "Name is required",
"email": "Invalid email format"
}
}{
"error": "Unauthorized",
"message": "Invalid API key"
}{
"error": "Rate Limit Exceeded",
"message": "Too many requests. Please wait before retrying.",
"details": {
"retry_after": 45
}
}Create Template
Create a new template with a base64-encoded PDF document. The API automatically extracts the page count from the document.
import { FirmaClient } from "@firma-dev/sdk";
const firma = new FirmaClient({ apiKey: "YOUR_API_KEY" });
const response = await firma.templates.createTemplate({
name: "Employment Contract Template",
document: "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c..."
});
console.log(response);curl --request POST \
--url https://api.firma.dev/functions/v1/signing-request-api/templates \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Employment Contract Template",
"document": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...",
"description": "Standard employment contract for new hires",
"expiration_hours": 168,
"settings": {
"allow_editing_before_sending": false,
"attach_pdf_on_finish": true,
"allow_download": true,
"hand_drawn_only": false,
"require_otp_verification": null,
"disable_guided_navigation": true,
"allow_presigning_download": true,
"show_qr_code": true
},
"document_id": "123e4567-e89b-12d3-a456-426614174000"
}
'import requests
url = "https://api.firma.dev/functions/v1/signing-request-api/templates"
payload = {
"name": "Employment Contract Template",
"document": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...",
"description": "Standard employment contract for new hires",
"expiration_hours": 168,
"settings": {
"allow_editing_before_sending": False,
"attach_pdf_on_finish": True,
"allow_download": True,
"hand_drawn_only": False,
"require_otp_verification": None,
"disable_guided_navigation": True,
"allow_presigning_download": True,
"show_qr_code": True
},
"document_id": "123e4567-e89b-12d3-a456-426614174000"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Employment Contract Template',
document: 'JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...',
description: 'Standard employment contract for new hires',
expiration_hours: 168,
settings: {
allow_editing_before_sending: false,
attach_pdf_on_finish: true,
allow_download: true,
hand_drawn_only: false,
require_otp_verification: null,
disable_guided_navigation: true,
allow_presigning_download: true,
show_qr_code: true
},
document_id: '123e4567-e89b-12d3-a456-426614174000'
})
};
fetch('https://api.firma.dev/functions/v1/signing-request-api/templates', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.firma.dev/functions/v1/signing-request-api/templates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Employment Contract Template',
'document' => 'JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...',
'description' => 'Standard employment contract for new hires',
'expiration_hours' => 168,
'settings' => [
'allow_editing_before_sending' => false,
'attach_pdf_on_finish' => true,
'allow_download' => true,
'hand_drawn_only' => false,
'require_otp_verification' => null,
'disable_guided_navigation' => true,
'allow_presigning_download' => true,
'show_qr_code' => true
],
'document_id' => '123e4567-e89b-12d3-a456-426614174000'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.firma.dev/functions/v1/signing-request-api/templates"
payload := strings.NewReader("{\n \"name\": \"Employment Contract Template\",\n \"document\": \"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...\",\n \"description\": \"Standard employment contract for new hires\",\n \"expiration_hours\": 168,\n \"settings\": {\n \"allow_editing_before_sending\": false,\n \"attach_pdf_on_finish\": true,\n \"allow_download\": true,\n \"hand_drawn_only\": false,\n \"require_otp_verification\": null,\n \"disable_guided_navigation\": true,\n \"allow_presigning_download\": true,\n \"show_qr_code\": true\n },\n \"document_id\": \"123e4567-e89b-12d3-a456-426614174000\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.firma.dev/functions/v1/signing-request-api/templates")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Employment Contract Template\",\n \"document\": \"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...\",\n \"description\": \"Standard employment contract for new hires\",\n \"expiration_hours\": 168,\n \"settings\": {\n \"allow_editing_before_sending\": false,\n \"attach_pdf_on_finish\": true,\n \"allow_download\": true,\n \"hand_drawn_only\": false,\n \"require_otp_verification\": null,\n \"disable_guided_navigation\": true,\n \"allow_presigning_download\": true,\n \"show_qr_code\": true\n },\n \"document_id\": \"123e4567-e89b-12d3-a456-426614174000\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.firma.dev/functions/v1/signing-request-api/templates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Employment Contract Template\",\n \"document\": \"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...\",\n \"description\": \"Standard employment contract for new hires\",\n \"expiration_hours\": 168,\n \"settings\": {\n \"allow_editing_before_sending\": false,\n \"attach_pdf_on_finish\": true,\n \"allow_download\": true,\n \"hand_drawn_only\": false,\n \"require_otp_verification\": null,\n \"disable_guided_navigation\": true,\n \"allow_presigning_download\": true,\n \"show_qr_code\": true\n },\n \"document_id\": \"123e4567-e89b-12d3-a456-426614174000\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"created_date": "2023-11-07T05:31:56Z",
"description": "<string>",
"document_url": "<string>",
"document_url_expires_at": "2023-11-07T05:31:56Z",
"page_count": 2,
"expiration_hours": 168,
"credit_cost": 1,
"settings": {
"allow_download": true,
"attach_pdf_on_finish": true,
"allow_editing_before_sending": false,
"use_signing_order": true,
"hand_drawn_only": false,
"send_signing_email": true,
"send_finish_email": true,
"send_expiration_email": true,
"send_cancellation_email": true,
"require_otp_verification": null,
"disable_guided_navigation": true,
"allow_presigning_download": true,
"show_qr_code": true,
"identity_editable_fields": [
"<string>"
],
"notify_identity_change_email": false
},
"recipients": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"email": "jsmith@example.com",
"first_name": "<string>",
"order": 2,
"name": "<string>",
"last_name": "<string>",
"phone_number": "<string>",
"street_address": "<string>",
"city": "<string>",
"state_province": "<string>",
"postal_code": "<string>",
"country": "<string>",
"title": "<string>",
"company": "<string>",
"required_fields": [
"<string>"
],
"missing_fields": [
"<string>"
],
"required_read_only_fields": [
{
"variable_name": "<string>",
"variable_defined_name": "<string>",
"field_type": "<string>"
}
],
"ready_to_send": true
}
],
"fields": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"page_number": 2,
"required": true,
"recipient_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"variable_name": "<string>",
"variable_defined_name": "<string>",
"position": {
"x": 50,
"y": 50,
"width": 50,
"height": 50
},
"dropdown_options": [
"<string>"
],
"multi_group_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"date_default": "2023-12-25",
"date_signing_default": true,
"format_rules": {
"dateFormat": "MMMM dd, yyyy"
},
"validation_rules": {},
"read_only": false,
"read_only_value": "<string>"
}
],
"updated_date": "2023-11-07T05:31:56Z"
}{
"error": "Validation Error",
"message": "Invalid input data",
"details": {
"name": "Name is required",
"email": "Invalid email format"
}
}{
"error": "Unauthorized",
"message": "Invalid API key"
}{
"error": "Rate Limit Exceeded",
"message": "Too many requests. Please wait before retrying.",
"details": {
"retry_after": 45
}
}Authorizations
API key for authentication. Use your API key directly without any prefix (e.g., 'your-api-key'). Bearer prefix is optional but not required.
Body
Template name
255"Employment Contract Template"
Base64-encoded PDF or DOCX document. DOCX files are automatically converted to PDF. Maximum size: 20MB. The API will automatically extract the page count from the document. (mutually exclusive with document_id)
"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c..."
Template description
"Standard employment contract for new hires"
Hours until signing request expires
168
Show child attributes
Show child attributes
ID of a previously uploaded document (mutually exclusive with document). Obtain by calling POST /documents first.
"123e4567-e89b-12d3-a456-426614174000"
Response
Template created successfully
Unique identifier for the template
Template name
255Template creation timestamp
Template description
Pre-signed URL to the PDF document. This is a time-limited signed URL for secure access - see document_url_expires_at for expiration time. Initial URLs are valid for 7 days; refreshed URLs are valid for 1 hour. Request a new template retrieval to get a fresh URL if expired.
ISO 8601 timestamp when the document_url will expire. After this time, the URL will return an access denied error. Fetch the template again to receive a fresh signed URL.
Number of pages in the document
x >= 1Hours until signing requests created from this template expire
x >= 1Number of credits consumed when a signing request is sent from this template. Minimum value is 1.
x >= 1Settings returned by the signing request list and detail endpoints. Templates use the TemplateSettings schema (no identity fields).
Show child attributes
Show child attributes
Template recipients (included in GET single template)
Show child attributes
Show child attributes
Template fields (included in GET single template)
Show child attributes
Show child attributes
Template last update timestamp
Was this page helpful?