Ready examples
The three things people do, in cURL, Python and JavaScript, ready to copy. Each
reads the key from the DOCONURE_API_KEY environment variable, never
from the code. For a test version of any of them, add
"isTest": true to settings: nothing is charged and the
document is marked TEST (How do I make a test call?).
Python uses requests (pip install requests); JavaScript
needs Node.js 18 or later and runs as an ES module (example.mjs).
Compose a document
cURL
curl -X POST https://app.doconure.com/api/v1/compose/documents/generate \
-H "Authorization: Bearer $DOCONURE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": { "title": "Order confirmation", "customer": { "name": "Rossi Costruzioni Srl" } },
"settings": { "templateId": "YOUR_TEMPLATE_ID" }
}' \
--dump-header headers.txt --output document.pdf
Python
import os
import requests
API = "https://app.doconure.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['DOCONURE_API_KEY']}"}
body = {
"data": {"title": "Order confirmation", "customer": {"name": "Rossi Costruzioni Srl"}},
"settings": {"templateId": "YOUR_TEMPLATE_ID"},
}
r = requests.post(f"{API}/compose/documents/generate", headers=HEADERS, json=body, timeout=120)
if r.status_code != 200:
err = r.json()
raise RuntimeError(f"{err['code']} ({err['number']}): {err['message']}")
with open("document.pdf", "wb") as f:
f.write(r.content)
print("document", r.headers["X-Document-Id"], "credits left", r.headers["X-Credits-Left"])
JavaScript
import { writeFile } from "node:fs/promises";
const API = "https://app.doconure.com/api/v1";
const headers = {
"Authorization": `Bearer ${process.env.DOCONURE_API_KEY}`,
"Content-Type": "application/json",
};
const r = await fetch(`${API}/compose/documents/generate`, {
method: "POST",
headers,
body: JSON.stringify({
data: { title: "Order confirmation", customer: { name: "Rossi Costruzioni Srl" } },
settings: { templateId: "YOUR_TEMPLATE_ID" },
}),
});
if (!r.ok) {
const err = await r.json();
throw new Error(`${err.code} (${err.number}): ${err.message}`);
}
await writeFile("document.pdf", Buffer.from(await r.arrayBuffer()));
console.log("document", r.headers.get("X-Document-Id"), "credits left", r.headers.get("X-Credits-Left"));
Send a document for signature
Over a document you composed (its X-Document-Id), created and sent in
one call. Always send an Idempotency-Key: this call charges and emails a
real person, and a retry without one does both again.
cURL
curl -X POST "https://app.doconure.com/api/v1/sign/envelopes?send=true" \
-H "Authorization: Bearer $DOCONURE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: contract-4471" \
-d '{
"signers": {
"A": { "email": "anna@example.com", "fullName": "Anna Rossi",
"fields": [{ "kind": "signature", "page": 1,
"x": 0.1, "y": 0.78, "width": 0.32, "height": 0.09 }] }
},
"settings": { "documentId": "THE_X-DOCUMENT-ID", "subject": "Please sign" }
}'
Python
body = {
"signers": {
"A": {
"email": "anna@example.com",
"fullName": "Anna Rossi",
"fields": [{"kind": "signature", "page": 1,
"x": 0.1, "y": 0.78, "width": 0.32, "height": 0.09}],
}
},
"settings": {"documentId": document_id, "subject": "Please sign"},
}
r = requests.post(
f"{API}/sign/envelopes", params={"send": "true"}, json=body, timeout=120,
headers={**HEADERS, "Idempotency-Key": f"contract-{document_id}"},
)
r.raise_for_status()
print("envelope", r.json()["output"]["sign"]["envelopeId"])
JavaScript
const sent = await fetch(`${API}/sign/envelopes?send=true`, {
method: "POST",
headers: { ...headers, "Idempotency-Key": `contract-${documentId}` },
body: JSON.stringify({
signers: {
A: {
email: "anna@example.com",
fullName: "Anna Rossi",
fields: [{ kind: "signature", page: 1, x: 0.1, y: 0.78, width: 0.32, height: 0.09 }],
},
},
settings: { documentId, subject: "Please sign" },
}),
});
const answer = await sent.json();
if (!sent.ok) throw new Error(`${answer.code}: ${answer.message}`);
console.log("envelope", answer.output.sign.envelopeId);
Compose and send for signature in one call
cURL
curl -X POST https://app.doconure.com/api/v1/flow \
-H "Authorization: Bearer $DOCONURE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4471" \
-d '{
"data": { "customer": { "name": "Acme Srl" } },
"settings": { "templateId": "YOUR_TEMPLATE_ID" },
"signature": {
"subject": "Service agreement",
"signers": {
"A": { "email": "anna@example.com", "fullName": "Anna Rossi",
"fields": [{ "kind": "signature", "page": 1,
"x": 0.1, "y": 0.78, "width": 0.32, "height": 0.09 }] }
}
}
}'
Python
body = {
"data": {"customer": {"name": "Acme Srl"}},
"settings": {"templateId": "YOUR_TEMPLATE_ID"},
"signature": {
"subject": "Service agreement",
"signers": {"A": {"email": "anna@example.com", "fullName": "Anna Rossi",
"fields": [{"kind": "signature", "page": 1,
"x": 0.1, "y": 0.78, "width": 0.32, "height": 0.09}]}},
},
}
r = requests.post(f"{API}/flow", json=body, timeout=120,
headers={**HEADERS, "Idempotency-Key": "order-4471"})
r.raise_for_status()
flow = r.json()["output"]["flow"]
print("flow", flow["flowId"])
JavaScript
const started = await fetch(`${API}/flow`, {
method: "POST",
headers: { ...headers, "Idempotency-Key": "order-4471" },
body: JSON.stringify({
data: { customer: { name: "Acme Srl" } },
settings: { templateId: "YOUR_TEMPLATE_ID" },
signature: {
subject: "Service agreement",
signers: {
A: {
email: "anna@example.com",
fullName: "Anna Rossi",
fields: [{ kind: "signature", page: 1, x: 0.1, y: 0.78, width: 0.32, height: 0.09 }],
},
},
},
}),
});
const flow = await started.json();
if (!started.ok) throw new Error(`${flow.code}: ${flow.message}`);
console.log("flow", flow.output.flow.flowId);
Next
- Which scope each call needs: Authentication.
- What an error means and when to retry: Outcomes and error codes.
- Knowing when a signature completed: How do I know when something finished?