DoConure

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