Guides
Templates and public links
A template stores a PDF, its recipient slots and its field layout. Create a document from it with one call instead of uploading and positioning fields every time.
Create a template#
Either upload a PDF with POST /templates (multipart, like documents) and then set its layout with PATCH, or turn an existing document (with its fields) into a template with POST /templates/from-document/{document_id} and body {"name": "...", "description": "...", "category": "..."}. Both need templates:write.
curl -sS -X POST "https://api.sign.yt/v1/templates" \
-H "Authorization: Bearer $SIGNYT_API_KEY" \
-F 'payload={"name":"Office lease","description":"Standard 12-month lease","category":"Leases"};type=application/json' \
-F "[email protected];type=application/pdf" | tee tpl.json
TEMPLATE_ID=$(jq -r .id tpl.json)
curl -sS -X PATCH "https://api.sign.yt/v1/templates/$TEMPLATE_ID" \
-H "Authorization: Bearer $SIGNYT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients_schema": [{"role": "SIGNER", "label": "Tenant"}],
"fields_schema": [
{"type": "SIGNATURE", "page": 3, "position_x": 10, "position_y": 82, "width": 30, "height": 7, "recipient_index": 0},
{"type": "DATE", "page": 3, "position_x": 60, "position_y": 84, "width": 18, "height": 4, "recipient_index": 0}
]
}'import os
import httpx
from signyt import Signyt
client = Signyt(os.environ["SIGNYT_API_KEY"])
tpl = client.templates.create("lease.pdf", name="Office lease", description="Standard 12-month lease", category="Leases")
# Layout is set with PATCH (no SDK method yet).
httpx.patch(
f"https://api.sign.yt/v1/templates/{tpl.id}",
headers={"Authorization": f"Bearer {os.environ['SIGNYT_API_KEY']}"},
json={
"recipients_schema": [{"role": "SIGNER", "label": "Tenant"}],
"fields_schema": [
{"type": "SIGNATURE", "page": 3, "position_x": 10, "position_y": 82, "width": 30, "height": 7, "recipient_index": 0},
],
},
).raise_for_status()import { readFile } from "node:fs/promises";
import { Signyt } from "@signyt/sdk";
const client = new Signyt(process.env.SIGNYT_API_KEY!);
const tpl = await client.templates.create({
pdf: await readFile("lease.pdf"),
name: "Office lease",
description: "Standard 12-month lease",
category: "Leases",
});
// Layout is set with PATCH (no SDK method yet).
await fetch(`https://api.sign.yt/v1/templates/${tpl.id}`, {
method: "PATCH",
headers: { Authorization: `Bearer ${process.env.SIGNYT_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
recipients_schema: [{ role: "SIGNER", label: "Tenant" }],
fields_schema: [
{ type: "SIGNATURE", page: 3, position_x: 10, position_y: 82, width: 30, height: 7, recipient_index: 0 },
],
}),
});| Template field | Notes |
|---|---|
name, description, category | 1-200, up to 1000 and up to 100 characters; category defaults to General. |
recipients_schema | Up to 50 slots: role (default SIGNER), label, optional fixed email/name, public (the slot filled by public-link visitors), require_phone. |
fields_schema | Up to 200 fields, same geometry as document fields, with recipient_index (slot position, 0-based) instead of recipient_id. |
template_type | Sharing: PRIVATE, TEAM_SHARED, ORG_SHARED (default) or PUBLIC_LINK; team_id for team templates. |
Replace the PDF while keeping the layout with PUT /templates/{id}/pdf (multipart pdf), for example when a contract gets a new version with the same layout. List, read and delete with GET /templates, GET /templates/{id} and DELETE /templates/{id}.
Create a document from a template#
POST /templates/{id}/use creates a draft with the template's PDF and fields. recipients (1-50) fill the slots in order; each item needs email and may have name (defaults to the part of the email before @). Recipients are created as signers in parallel order with no extra verification. Send the draft as usual.
DOC_ID=$(curl -sS -X POST "https://api.sign.yt/v1/templates/$TEMPLATE_ID/use" \
-H "Authorization: Bearer $SIGNYT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: lease-$(uuidgen)" \
-d '{"title": "Office lease - Anna Nowak", "recipients": [{"email": "[email protected]", "name": "Anna Nowak"}]}' \
| jq -r .id)
curl -sS -X POST "https://api.sign.yt/v1/documents/$DOC_ID/send" \
-H "Authorization: Bearer $SIGNYT_API_KEY" -H "Idempotency-Key: send-$DOC_ID"import os
from signyt import Signyt
client = Signyt(os.environ["SIGNYT_API_KEY"])
doc = client.templates.use(
os.environ["TEMPLATE_ID"],
title="Office lease - Anna Nowak",
recipients=[{"email": "[email protected]", "name": "Anna Nowak"}],
)
client.documents.send(doc.id)import { Signyt } from "@signyt/sdk";
const client = new Signyt(process.env.SIGNYT_API_KEY!);
const doc = await client.templates.use(process.env.TEMPLATE_ID!, {
title: "Office lease - Anna Nowak",
recipients: [{ email: "[email protected]", name: "Anna Nowak" }],
});
await client.documents.send(doc.id);The new document's metadata records the template, so flows can trigger when "a document of template X completes".
Public links#
A public link lets anyone fill in and sign a template: each visitor enters their name and email (and phone if the slot requires it) and gets their own document. Typical uses are onboarding forms, consents and applications.
- Enable or rotate:
POST /templates/{id}/public-linkwith optional{"expires_at": "...", "max_uses": 500}. The response containsurlandtoken; rotating invalidates the previous link. - Inspect:
GET /templates/{id}/public-link(enabled,expires_at,max_uses,uses). Disable:DELETE /templates/{id}/public-link. - QR code for print:
GET /templates/{id}/public-link/qr.png. - Only organization or team admins can enable public links. The visitors' slot is the one marked
public, otherwise the first signer slot; every other slot needs a fixed email (409 template_roles_incomplete). - Abuse protection: visitor starts are limited per IP and per template per hour, and a CAPTCHA may be required.
curl -sS -X POST "https://api.sign.yt/v1/templates/$TEMPLATE_ID/public-link" \
-H "Authorization: Bearer $SIGNYT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"max_uses": 500}'
# {"enabled": true, "url": "https://sign.yt/t/public/Xk2...", "token": "Xk2...", "uses": 0, ...}
curl -sS -o lease-qr.png "https://api.sign.yt/v1/templates/$TEMPLATE_ID/public-link/qr.png" \
-H "Authorization: Bearer $SIGNYT_API_KEY"Template catalog#
GET /template-catalog (filters category, language) and GET /template-catalog/{blueprint_id} return a small built-in catalog of common agreement types with suggested recipient roles, fields and verification. Entries are metadata only (no PDF); use them to pre-fill your own UI.