Contract generation API
Generate contracts from your platform’s data.
A contract generation API produces a finished agreement from a template and structured data, inside another product. Conovo’s starts from the document your users already send: AI proposes which parts vary, a human confirms them, the confirmed fields bind to your platform’s own schema, and every send resolves, computes, validates, and generates the contract in deterministic code. No model output reaches the finished document.
It is not a signature API and not a PDF renderer. Those handle the steps either side of the hard part: deciding what each field of an agreement should say, computing the values that depend on other values, and refusing to send when the result doesn’t hold up.
Who this is for
The buyer is a platform team, not a legal department.
You already store everything the contract needs.
If your product knows the parties, the amounts, the dates and the scope, it already holds every value the agreement is missing. What it doesn’t have is the pipeline between that record and an executed document, and that pipeline is most of a year of engineering that has nothing to do with your product.
- Vertical SaaS platforms whose users send agreements to their own customers: wealth and investment, construction and contracting, staffing and recruiting, professional services, insurance, logistics.
- Teams who tried the signature API first and discovered it starts one step after their real problem. Someone still has to produce the document.
- Products where contracts are a feature, not the product. You want this to work and then stop needing your attention.
How it works
Setup once per template; every send after is code.
Four steps, and only the first involves a model.
Register your payload schema
One JSON sample of the record a contract is about: your deal, matter, project, or policy. Versions are append-only, so extending the schema never invalidates a template that was bound against an earlier one.
Your user uploads the contract they already send
AI proposes the variable fields, the formulas between them, the signing parties, repeating tables, and clauses that only sometimes apply. Each proposal is confirmed or edited by a human before anything is saved, and each confirmed field stores the exact offsets it occupies in the document.
On PDFs, plainly: PDFs generate as well as DOCX, by filling the document’s own form fields, or drawing values over the located blanks when it has none. Word is the higher-fidelity path and the gap is named rather than hidden: no reflow, so an oversized value is reported as a failed fill instead of overlapping neighbouring text.
Fields bind to your schema
Each field resolves from a binding into your payload, a standing value the business set once, a formula over other fields, or a question asked at send time. A binding that cannot resolve degrades to a question rather than an error, and the miss is reported back so you can close the gap in your schema.
Send resolves, validates, and generates
Values resolve by priority, money and date arithmetic runs through a decimal-safe evaluator, the result is validated, and the document is filled from the stored anchors. A contract that fails validation becomes a draft for review. Silent failure is not a path through this code.
// Your server already knows the deal. Hand it over and read back a contract. const contract = await fetch('https://api.conovo.co/v1/contracts', { method: 'POST', headers: { authorization: `Bearer ${sessionToken}`, // minted by @conovo/node 'content-type': 'application/json', }, body: JSON.stringify({ templateVersionId, subject: deal, // your own record, matching your payload schema recipients: [{ name: client.fullName, email: client.email }], }), }).then((r) => r.json()) // contract.status is 'draft' or 'needs_attention' — never a silent send. // contract.issues carries plain-English reasons when it needs attention.
Most platforms never write this call. <SendContract /> does it, with the review panel, the typed questions, and the draft preview already built. The endpoint is here because you should be able to see what the component is doing. Full integration in the docs.
Determinism
The claim that makes this usable for real agreements.
No model output lands in a contract.
AI is used at setup, to propose structure a human then confirms. On the send path, resolution, arithmetic and formatting are ordinary code, so the same inputs always produce the same document.
- Money and dates never touch a model. Formulas are stored as data and evaluated by a decimal-safe expression evaluator. A language model cannot be trusted with arithmetic that appears in an executed agreement, so it is never asked to do any.
- Validation gates every send. Empty required fields, inconsistent math and cross-field contradictions hold the contract as a draft with plain-English issues attached.
- The one send-path model call can only subtract. On unattended sends an optional anomaly check looks for values that are wrong-but-plausible. Its only power is to hold the contract back for a human. It has no path to alter a word of the document.
- Every contract is reproducible. Versioned templates, pinned versions, stored resolved values.
Limits
Named here rather than discovered in week three.
What this API does not do.
- It does not reflow a PDF. PDFs generate, but a value materially longer than the blank it replaces is reported as a failed fill rather than overlapping the text beside it. Covering a blank also assumes a plain background, and the font is matched by size rather than family.
- Repeating tables and conditional sections are DOCX-only. Cloning a row and removing a clause’s paragraphs need document structure a flattened PDF does not expose; on a PDF they report as unsupported rather than silently doing nothing.
- It does not write contract language. Conovo fills the agreement your user already uses. It does not invent clauses, and it is not a drafting tool.
- It is not legal advice or review. Conovo is software infrastructure, not a law firm.
- It is not self-hostable today. The SDK talks only to Conovo’s API with a short-lived token your server mints, which is what keeps document content out of your infrastructure.
Questions
What developers ask before writing the first call.
Common questions.
What is a contract generation API?
A contract generation API produces a finished agreement from a template and structured data, over HTTP, inside another product. It differs from a signature API, which collects signatures on a document you have already produced, and from a PDF rendering API, which draws a document you have already composed. A contract generation API owns the step in between: deciding what each field of the agreement should say, computing the values that depend on other values, checking the result, and emitting the document.
How does Conovo know which parts of the contract to fill?
At setup, AI reads the uploaded document and proposes which passages vary: parties, amounts, dates, payment schedules, repeating tables, and clauses that only sometimes apply. Each proposal is confirmed or edited by a human before it is saved, and each confirmed field records the exact character offsets it occupies in the source document. At send time, generation is a lookup against those stored anchors, no model reads the document again.
Where does the data come from?
From the record your platform already stores. You register a payload schema once, bindings map each contract field to a path in it, and at send time you pass the record. Anything a binding cannot resolve falls through to a typed question your user answers in the panel, and the miss is reported back so you can extend the schema and stop being asked next time.
Can the API generate a contract without any user interaction?
Yes, once a template has earned it. Unattended sends unlock after three contracts from that template have been reviewed and sent by a human, which is a deliberate ramp rather than a setting. Any validation flag on an unattended send demotes it to a draft for review instead of dispatching it, and an optional anomaly check can hold it back as well. The check is read-only: it can stop a send, never alter one.
What happens when generation fails?
It fails as a draft, never as a silent send. An empty required field, arithmetic that contradicts itself, or a cross-field inconsistency puts the contract into a needs-attention state with plain-English issues attached, and dispatch is refused until it is resolved. Drafts are not billed, so the safe behaviour and the cheap behaviour are the same behaviour.
Is the generated document reproducible?
Yes. Templates are versioned, every contract pins the version it was generated from, and the exact resolved values used at generation are stored alongside it. A contract signed today can be regenerated byte-for-byte later from its pinned version and stored values, which is what makes the audit trail meaningful rather than decorative.
Next
Generate one against the sandbox.
Real extraction, real documents, real webhooks, before you enter a card. Related reading: template automation, embedded e-signature, and build versus buy.