Developers
Build with the Conovo API and SDK.
Conovo integrates as two npm packages and one server route. Your server mints a short-lived session token from your secret key; React components mounted in your product use it to set up templates, generate contracts from your own records, and dispatch them for signature. Workspace scope travels in the token, so you never pass a tenant identifier from the client.
npm i @conovo/node @conovo/react
Packages
MIT, typed, published publicly.
Four packages; you need two.
@conovo/node
Mints short-lived session tokens from your secret key, and verifies inbound webhook and connector signatures. Zero dependencies.
@conovo/react
The provider plus the embeddable surfaces: template setup, sending, bulk send, the contract inbox, standing terms, and the recipient signing view.
@conovo/core
The shared field taxonomy and value shapes. Your editor gets the same types the API validates against, so a wrong field type is a compile error.
@conovo/mcp
An MCP server for your own coding agent: register payload schemas, read payload gaps, mint sandbox sessions, inspect requests and events. No tool touches live contract content.
The integration
A server route and a component.
What the whole surface looks like.
This is not an excerpt of a longer integration. The session route and the mounted component are substantially the whole thing. Everything else is choosing where the components live in your product.
// app/api/conovo/session/route.ts (your server, your auth) import { Conovo } from '@conovo/node' const conovo = new Conovo({ secretKey: process.env.CONOVO_SECRET_KEY }) export async function POST() { const org = await currentOrg() // however you resolve the signed-in business const session = await conovo.sessions.create({ workspace: { externalRef: org.id, name: org.name }, user: { id: currentUser.id, role: 'owner' }, // optional, for the audit trail }) return Response.json(session) // { token, expiresAt }, valid 15 minutes }
// Wherever contracts belong in your product import { SendContract } from '@conovo/react' export function DealContract({ deal, client }) { return ( <SendContract subject={deal} defaultRecipient={{ name: client.fullName, email: client.email }} onSent={(contractId) => router.push(`/deals/${deal.id}/contracts/${contractId}`)} /> ) }
Evaluating
What you can check before committing.
Things worth verifying yourself.
- Test mode is honest. Test keys stamp contracts as test, never reach a real signing provider, are not metered, and cannot unlock unattended sending. Webhook payloads carry the flag.
- The API reference is generated, not written. Request bodies come from the same schemas the routes validate with, so the docs cannot drift from the behaviour.
- Errors are meant to be shown. RFC 7807 problem+json with machine-readable reasons and messages written for your users.
- Your agent can do the setup. @conovo/mcp exposes schema registration, payload gaps, sandbox sessions and the request inspector as MCP tools.
- Upload a real contract. The sandbox runs real extraction on a real document without a card, which is the fastest way to find out whether this fits your users’ agreements.
Questions
Before the first commit.
Common questions.
What does the integration actually require?
Three things. A registered payload schema describing the record contracts are about; one server route that mints a session token with @conovo/node; and React components mounted where contracts belong in your product. There is no webhook you must implement to get started, no document storage on your side, and no workspace provisioning step: the first session minted for an external reference creates the workspace.
How is authentication handled?
Your secret key stays on your server and mints short-lived session tokens, which are what the browser holds. Scope is carried in the token claims rather than in requests, so a session minted for one business cannot read another's templates or contracts regardless of what the client sends. Entitlement is re-checked on every API route, not just at minting.
Is there an API reference?
Yes. An OpenAPI 3.1 document served by the API itself, with a browsable reference alongside it. Request bodies are generated from the same schemas the routes validate against, so the documentation cannot drift from the validation.
Can we build against it without paying?
Yes. Test-mode keys mint tokens carrying a test claim, and everything downstream honours it: contracts are stamped as test, dispatch never reaches a real signing provider, usage is not metered, and test traffic cannot unlock unattended sending. Webhook payloads carry the flag so your own handlers can branch on it.
What do errors look like?
RFC 7807 problem+json with a machine-readable reason, and plain-English messages intended to be shown to your users rather than logged and hidden. Entitlement failures are 402 with a reason your product can branch on, so a lapsed account renders as your empty state instead of a stack trace.
Can we style the components?
They are scoped under a single class and driven entirely by CSS custom properties, so overriding accent, radius and typography in your own stylesheet is enough to make them read as your product. Components also expose render slots where an action belongs to your application rather than to Conovo.
Next
Six steps to a generated contract.
The docs go from secret key to sent contract in order. Background reading: the generation API, template setup, and how data is handled.