Template Update
This service allows you to update custom templates that can later be used to fill out documents for signature.
/templateprivate keyprk_Authentication
Include your private key in the Authorization header.
Authorization: prk_xxx...
Update Parameters
| Name | Type | Description |
|---|---|---|
id | String required | Template identifier. |
name | String required | Name of the automation. |
description | String optional | Text describing the template, up to 500 characters. |
config | Array required | Array of questions for the user. See JSON Configuration. |
signatureProfile | Array required | Definition of signers and approvers. See Signature Profiles. |
sign | Array required | Names of required questions. |
preBuild | Boolean optional | If true, includes automatic pre-fill. |
PUT /template validates the body the same way as POST /template: name, config, sign, and signatureProfile are required even if they do not change, and the API responds 400 if any is missing. The safest approach is to start from what GET /template?id= returns, change what you need, and send it back without urls, which the API does not accept on write.
description is kept if you do not send itLeaving description out of the PUT does not erase the description the template already has: the
previous one stays. To change it, send the new text — up to 500 characters, or the API responds
400.
Today there is no way to leave a template without a description once it has one: the validation
rejects both the empty string ("") and null, and omitting the field keeps the previous value. If
you need the text to stop showing, replace it with the right one.
Update Examples
- curl
- Python
- Node.js
curl -X PUT https://api.auco.ai/v1.5/ext/template \
-H "Content-Type: application/json" \
-H "Authorization: prk_private_key_company" \
-d '{
"id": "64823dc5ce28a265e02d68f3",
"name": "Test document variable modification",
"description": "Service agreement with a single signer, for the sales team",
"config": [
{
"name": "new_question",
"type": "name",
"description": "Example of new question"
},
{
"name": "client_name",
"type": "name",
"description": "Enter the client name"
},
{
"description": "Select the document type for the client",
"name": "client_document_type",
"type": "clausula",
"value": "id_card",
"options": [
{
"name": "National ID Card",
"value": "id_card"
},
{
"name": "Foreign ID Card",
"value": "foreign_id"
}
]
},
{
"description": "Enter the national ID card number for the client",
"name": "client_id_card",
"type": "number",
"prereq": [
{
"k": "client_document_type",
"v": "id_card"
}
]
},
{
"description": "Enter the foreign ID number for the client",
"name": "client_foreign_id",
"type": "number",
"prereq": [
{
"k": "client_document_type",
"v": "foreign_id"
}
]
},
{
"name": "client_email",
"type": "email",
"description": "Enter the client email"
},
{
"name": "client_phone",
"type": "phone",
"description": "Enter the client phone"
}
],
"sign": [
"client_name",
"client_id_card",
"client_foreign_id",
"client_email",
"client_phone",
"new_question"
],
"signatureProfile": [
{
"email": "client_email",
"phone": "client_phone",
"identification": "client_id_card|client_foreign_id",
"name": "client_name",
"type": "client"
}
]
}'
import requests
import json
template_data = {
"id": "64823dc5ce28a265e02d68f3",
"name": "Test document variable modification",
"description": "Service agreement with a single signer, for the sales team",
"config": [
{
"name": "new_question",
"type": "name",
"description": "Example of new question"
},
{
"name": "client_name",
"type": "name",
"description": "Enter the client name"
},
{
"description": "Select the document type for the client",
"name": "client_document_type",
"type": "clausula",
"value": "id_card",
"options": [
{
"name": "National ID Card",
"value": "id_card"
},
{
"name": "Foreign ID Card",
"value": "foreign_id"
}
]
},
{
"description": "Enter the national ID card number for the client",
"name": "client_id_card",
"type": "number",
"prereq": [
{
"k": "client_document_type",
"v": "id_card"
}
]
},
{
"description": "Enter the foreign ID number for the client",
"name": "client_foreign_id",
"type": "number",
"prereq": [
{
"k": "client_document_type",
"v": "foreign_id"
}
]
},
{
"name": "client_email",
"type": "email",
"description": "Enter the client email"
},
{
"name": "client_phone",
"type": "phone",
"description": "Enter the client phone"
}
],
"sign": [
"client_name",
"client_id_card",
"client_foreign_id",
"client_email",
"client_phone",
"new_question"
],
"signatureProfile": [
{
"email": "client_email",
"phone": "client_phone",
"identification": "client_id_card|client_foreign_id",
"name": "client_name",
"type": "client"
}
]
}
def update_template():
url = "https://api.auco.ai/v1.5/ext/template"
headers = {
"Content-Type": "application/json",
"Authorization": "prk_private_key_company"
}
try:
response = requests.put(
url,
json=template_data,
headers=headers
)
response.raise_for_status()
result = response.json()
print("Template updated successfully!")
print(f"Mask URL: {result['urls']['mask']}")
print(f"Complete URL: {result['urls']['complete']}")
return result
except requests.exceptions.RequestException as error:
print(f"Error updating template: {error.response.json() if hasattr(error, 'response') else error}")
if __name__ == "__main__":
update_template()
const axios = require('axios');
const templateData = {
id: '64823dc5ce28a265e02d68f3',
name: 'Test document variable modification',
description: 'Service agreement with a single signer, for the sales team',
config: [
{
name: 'new_question',
type: 'name',
description: 'Example of new question',
},
{
name: 'client_name',
type: 'name',
description: 'Enter the client name',
},
{
description: 'Select the document type for the client',
name: 'client_document_type',
type: 'clausula',
value: 'id_card',
options: [
{
name: 'National ID Card',
value: 'id_card',
},
{
name: 'Foreign ID Card',
value: 'foreign_id',
},
],
},
{
description: 'Enter the national ID card number for the client',
name: 'client_id_card',
type: 'number',
prereq: [
{
k: 'client_document_type',
v: 'id_card',
},
],
},
{
description: 'Enter the foreign ID number for the client',
name: 'client_foreign_id',
type: 'number',
prereq: [
{
k: 'client_document_type',
v: 'foreign_id',
},
],
},
{
name: 'client_email',
type: 'email',
description: 'Enter the client email',
},
{
name: 'client_phone',
type: 'phone',
description: 'Enter the client phone',
},
],
sign: [
'client_name',
'client_id_card',
'client_foreign_id',
'client_email',
'client_phone',
'new_question',
],
signatureProfile: [
{
email: 'client_email',
phone: 'client_phone',
identification: 'client_id_card|client_foreign_id',
name: 'client_name',
type: 'client',
},
],
};
async function updateTemplate() {
try {
const response = await axios.put('https://api.auco.ai/v1.5/ext/template', templateData, {
headers: {
'Content-Type': 'application/json',
Authorization: 'prk_private_key_company',
},
});
console.log('Template updated successfully!');
console.log('Mask URL:', response.data.urls.mask);
console.log('Complete URL:', response.data.urls.complete);
return response.data;
} catch (error) {
console.error('Error updating template:', error.response?.data || error.message);
}
}
updateTemplate();
Response Example
{
"urls": {
"mask": "https://signed_url_mask",
"complete": "https://signed_url_complete"
}
}
Uploading HTML Complete and HTML Mask:
You will need to upload the HTML files again. In the update service response, you will find two signed URLs, one for each
HTML. They have a lifespan of 120 seconds: after that, they are no longer valid. Have the HTML Complete and HTML Mask
files ready before updating the template and upload each one, as is, in a PUT request to its URL.
Content-Type: binary/octet-streamThe URLs are signed for that content type: if you send another one —for example text/html—, the upload is rejected. Send the file untransformed: in curl use --data-binary, not -d, which strips line breaks.
- curl
- Python
- Node.js
# Upload HTML Mask
curl -X PUT https://signed_url_mask \
-H "Content-Type: binary/octet-stream" \
--data-binary @mask.html
# Upload HTML Complete
curl -X PUT https://signed_url_complete \
-H "Content-Type: binary/octet-stream" \
--data-binary @complete.html
import requests
def upload_html_files(mask_url, complete_url):
"""
Uploads HTML files to the signed URLs
Args:
mask_url (str): Signed URL for the HTML Mask
complete_url (str): Signed URL for the HTML Complete
"""
try:
# Read HTML files
with open('mask.html', 'rb') as f:
mask_html = f.read()
with open('complete.html', 'rb') as f:
complete_html = f.read()
headers = {'Content-Type': 'binary/octet-stream'}
# Upload Mask HTML
response_mask = requests.put(mask_url, data=mask_html, headers=headers)
print(f"Mask HTML uploaded: {response_mask.status_code}")
# Upload Complete HTML
response_complete = requests.put(complete_url, data=complete_html, headers=headers)
print(f"Complete HTML uploaded: {response_complete.status_code}")
except requests.exceptions.RequestException as error:
print(f"Error uploading: {error}")
# Usage from the previous response
mask_url = "https://signed_url_mask"
complete_url = "https://signed_url_complete"
upload_html_files(mask_url, complete_url)
const fs = require('fs');
const axios = require('axios');
/**
* Uploads HTML files to the signed URLs
* @param {string} maskUrl - Signed URL for the HTML Mask
* @param {string} completeUrl - Signed URL for the HTML Complete
*/
async function uploadHtmlFiles(maskUrl, completeUrl) {
try {
// Read HTML files
const maskHtml = fs.readFileSync('mask.html');
const completeHtml = fs.readFileSync('complete.html');
const headers = { 'Content-Type': 'binary/octet-stream' };
// Upload Mask HTML
await axios.put(maskUrl, maskHtml, { headers });
console.log('Mask HTML uploaded successfully');
// Upload Complete HTML
await axios.put(completeUrl, completeHtml, { headers });
console.log('Complete HTML uploaded successfully');
} catch (error) {
console.error('Error uploading files:', error.message);
}
}
// Usage from the previous response
const maskUrl = 'https://signed_url_mask';
const completeUrl = 'https://signed_url_complete';
uploadHtmlFiles(maskUrl, completeUrl);
If they expire before you upload the files, call PUT /template again: each call returns new URLs.
If you're only updating config, sign, or signatureProfile and the HTML is unchanged, you can ignore the returned URLs and skip the upload entirely. The server will keep the HTMLs from the previous version.
⚠️ Error Responses
Errors come with the body { "message": "..." }.
| Code | Description |
|---|---|
| 400 | Invalid body or template not found: DOCUMENT_NOT_FOUND (the id does not match a template of your organization), PAYLOAD_NOT_VALID (the body is not JSON), PROFILE_FIELD_NOT_FOUND: <field> (a signer's email or phone is neither a config question nor a preFill field), PROFILE_FIELD_TYPE_INVALID: <field> must be type <type> (it points to a question of another type), or the validator's message |
| 401 | Invalid or missing authentication |
The validator's message names the failing field, for example "signatureProfile" is required, "config[0].maxLength" is not allowed, or "signatureProfile[0].name" must be a string. See the rules for each field in JSON Configuration.
The validation of email and phone in signatureProfile is newer than many templates. A template that still fills out without issues may be rejected by the PUT with PROFILE_FIELD_TYPE_INVALID, almost always because the signer's email is asked with a text question. Change that question's type to email in the same PUT.