
Product
Introducing Manifest Alerts
Socket now detects supply chain risks in project manifests, starting with missing lockfiles that can make dependency installs non-reproducible.
@chaindoc_io/server-sdk
Advanced tools
Server-side SDK for Chaindoc API - document management, signatures, and embedded sessions
Official server-side SDK for Chaindoc API - documents, signatures, contracts, invoicing, and webhook-safe integrations.
npm install @chaindoc_io/server-sdk
yarn add @chaindoc_io/server-sdk
pnpm add @chaindoc_io/server-sdk
import { Chaindoc } from "@chaindoc_io/server-sdk";
const chaindoc = new Chaindoc({
secretKey: "sk_your_secret_key",
});
// Create embedded session for document signing
const session = await chaindoc.embedded.createSession({
email: "signer@example.com",
metadata: {
documentId: "doc_xxx",
signatureRequestId: "req_xxx",
},
});
// Use session.sessionId on frontend with @chaindoc_io/embed-sdk
console.log(session.sessionId);
import { Chaindoc } from "@chaindoc_io/server-sdk";
import { readFile } from "fs/promises";
const chaindoc = new Chaindoc({
secretKey: "sk_your_secret_key",
});
// 1. Upload document
const buffer = await readFile("./contract.pdf");
const file = new Blob([buffer], { type: "application/pdf" });
const { media } = await chaindoc.media.upload([file]);
// 2. Create document with blockchain verification
const doc = await chaindoc.documents.create({
name: "Service Agreement",
description: "Contract for services",
media: media[0],
hashtags: ["#contract", "#agreement"],
status: "published", // Verify in blockchain
});
// 3. Create signature request
const request = await chaindoc.signatures.createRequest({
versionId: doc.document.currentVersion.id,
recipients: [{ email: "signer@example.com" }],
deadline: new Date("2027-12-31"),
embeddedFlow: true,
isKycRequired: true,
});
// 4. Create embedded session for signer
const session = await chaindoc.embedded.createSession({
email: "signer@example.com",
metadata: {
documentId: doc.documentId,
signatureRequestId: request.requestId,
returnUrl: "https://yourapp.com/signing-complete",
},
});
// 5. Send sessionId to frontend
// Frontend uses: @chaindoc_io/embed-sdk
// sdk.openSignatureFlow({ sessionId: session.sessionId })
import { Chaindoc } from "@chaindoc_io/server-sdk";
const chaindoc = new Chaindoc({
secretKey: "sk_your_secret_key",
});
// Contract should already be created, sent, and signed by both parties
const contract = await chaindoc.contracts.get("contract_uuid");
const contractId = contract.contractId;
if (contract.contract.status !== "active") {
throw new Error("Invoices can be created only for active contracts");
}
const invoice = await chaindoc.invoices.create(contractId, {
title: "April Retainer",
amount: "1500.00",
dueDate: "2026-04-30T00:00:00.000Z",
sendImmediately: false,
});
const invoiceId = invoice.invoiceId ?? invoice.invoice.id;
await chaindoc.invoices.send(contractId, invoiceId, {
autoCharge: false,
});
const refreshedInvoice = await chaindoc.invoices.get(contractId, invoiceId);
if (refreshedInvoice.invoice.status === "unpaid") {
await chaindoc.invoices.charge(contractId, invoiceId);
}
const transactions = await chaindoc.transactions.listByContract(contractId);
console.log(transactions.transactions.map((transaction) => transaction.id));
import { Chaindoc } from "@chaindoc_io/server-sdk";
const chaindoc = new Chaindoc({
secretKey: "sk_your_secret_key",
});
const templateId = "template_uuid";
const draftDocument = await chaindoc.templates.createDocument(templateId, {
documentName: "Generated NDA",
documentDescription: "Rendered from a published Chaindoc template",
variables: {
client_name: "Acme Inc.",
effective_date: "2026-04-10",
},
});
const signatureRequest = await chaindoc.templates.sendForSigning(templateId, {
documentName: "Generated NDA",
documentDescription: "Ready for signing",
variables: {
client_name: "Acme Inc.",
effective_date: "2026-04-10",
},
slotAssignments: [{ signerKey: "party_a", email: "signer@example.com" }],
deadline: new Date("2026-12-31"),
});
const contract = await chaindoc.templates.createContract(templateId, {
title: "Generated Master Services Agreement",
description: "Contract rendered from template",
variables: {
company_name: "Acme Inc.",
effective_date: "2026-04-10",
},
contragent: {
email: "partner@example.com",
name: "Partner Corp",
},
slotAssignments: [
{ signerKey: "party_a", role: "business" },
{ signerKey: "party_b", role: "contragent" },
],
deadline: new Date("2026-12-31"),
});
console.log(draftDocument.documentId);
console.log(signatureRequest.requestId);
console.log(contract.contractId);
const chaindoc = new Chaindoc({
secretKey: "sk_xxx", // Required - Your secret API key
environment: "production", // Optional: 'production' | 'staging' | 'development'
timeout: 30000, // Optional: Request timeout in ms (default: 30000)
retry: {
// Optional: Retry configuration
maxRetries: 3,
initialDelay: 1000,
maxDelay: 10000,
},
});
| Environment | API URL | Use Case |
|---|---|---|
production | https://api.chaindoc.io (default) | Live production traffic |
staging | https://api-demo.chaindoc.io | Pre-release testing |
development | https://api-demo.chaindoc.io | Development & debugging |
The SDK trims and lowercases every email value before sending it to the API. This applies to top-level fields (email, signerEmail) and to nested email fields inside recipients, fields, slotAssignments, accessEmails, and contragent. Your input objects are not mutated — the SDK copies them shallowly before normalizing. This matches the backend's canonical email format and prevents silent auto-link misses for users who registered with a different case.
// Create document
await chaindoc.documents.create({
name: string;
description: string;
media: Media;
hashtags: string[];
status: 'draft' | 'published';
accessType?: 'private' | 'public' | 'restricted';
});
// Update document (creates new version)
await chaindoc.documents.update(documentId, params);
// Update access rights
await chaindoc.documents.updateRights(documentId, {
accessType: 'restricted',
accessEmails: [{ email: 'user@example.com', level: 'read' }],
});
// Verify document in blockchain
await chaindoc.documents.verify({ versionHash: '0x...' });
// Get verification status
await chaindoc.documents.getVerificationStatus(versionId);
// Create signature request
await chaindoc.signatures.createRequest({
versionId: string;
recipients: [{ email: string }];
deadline: Date;
embeddedFlow?: boolean;
isKycRequired?: boolean;
});
// Get request status
await chaindoc.signatures.getRequestStatus(requestId);
// Get all requests
await chaindoc.signatures.getMyRequests({ pageNumber: 1, pageSize: 10 });
// Sign document
await chaindoc.signatures.sign({ requestId, signatureId });
// Create session for frontend signing (sends OTP to email)
const session = await chaindoc.embedded.createSession({
email: 'signer@example.com',
metadata: {
documentId: string;
signatureRequestId?: string;
returnUrl?: string;
},
});
// Returns sessionId for @chaindoc_io/embed-sdk
const created = await chaindoc.contracts.create({
documentId: "doc_uuid",
title: "Master Services Agreement",
contragent: { email: "partner@example.com", name: "Partner LLC" },
paymentMethodRequired: true,
preferredPaymentMethodType: "card",
});
await chaindoc.contracts.list({ page: 1, limit: 10, status: "active" });
await chaindoc.contracts.get(created.contractId);
await chaindoc.contracts.getStatus(created.contractId);
await chaindoc.contracts.getActivities(created.contractId);
await chaindoc.contracts.send(created.contractId, {
messageToSigners: "Please review and sign this contract",
deadline: new Date("2026-12-31"),
isKycRequired: true,
});
await chaindoc.contracts.cancel(created.contractId);
await chaindoc.contracts.terminate(created.contractId, { reason: "Mutual offboarding" });
await chaindoc.templates.createDocument(templateId, {
documentName: "Generated NDA",
variables: {
client_name: "Acme Inc.",
},
});
await chaindoc.templates.sendForSigning(templateId, {
documentName: "Generated NDA",
variables: {
client_name: "Acme Inc.",
},
slotAssignments: [{ signerKey: "party_a", email: "signer@example.com" }],
deadline: new Date("2026-12-31"),
});
await chaindoc.templates.createContract(templateId, {
title: "Generated MSA",
variables: {
company_name: "Acme Inc.",
},
contragent: {
email: "partner@example.com",
},
slotAssignments: [
{ signerKey: "party_a", role: "business" },
{ signerKey: "party_b", role: "contragent" },
],
deadline: new Date("2026-12-31"),
});
await chaindoc.invoices.create(contractId, {
title: "April Retainer",
amount: "1500.00",
dueDate: "2026-04-30T00:00:00.000Z",
autoCharge: false,
sendImmediately: false,
});
await chaindoc.invoices.list(contractId, { status: "unpaid", page: 1, limit: 20 });
await chaindoc.invoices.get(contractId, invoiceId);
await chaindoc.invoices.send(contractId, invoiceId, { autoCharge: true });
await chaindoc.invoices.charge(contractId, invoiceId);
await chaindoc.invoices.markPaid(contractId, invoiceId, { note: "Wire received" });
await chaindoc.transactions.listByContract(contractId);
await chaindoc.transactions.get(transactionId);
// Upload files (PDF, DOC, images, videos)
const { media } = await chaindoc.media.upload([file1, file2]);
// Get API key info
await chaindoc.getApiKeyInfo();
// Health check
await chaindoc.healthCheck();
const verification = Chaindoc.webhooks.verify(
rawBody,
req.headers["x-chaindoc-signature"] as string,
req.headers["x-chaindoc-timestamp"] as string,
process.env.CHAINDOC_WEBHOOK_SECRET!
);
if (!verification.valid) {
throw new Error("Invalid webhook signature");
}
switch (verification.envelope?.type) {
case "contract.signed":
case "invoice.created":
case "invoice.sent":
case "invoice.paid":
case "transaction.created":
case "transaction.updated":
console.log(verification.envelope.data);
break;
}
import { Chaindoc, ChaindocError } from '@chaindoc_io/server-sdk';
try {
await chaindoc.documents.create({ ... });
} catch (error) {
if (error instanceof ChaindocError) {
console.error('API Error:', error.message);
console.error('Status:', error.statusCode);
console.error('Response:', error.response);
}
}
sk_xxx) from Chaindoc Dashboard@chaindoc_io/embed-sdk - Frontend SDK for embedded signingWe welcome contributions! Please see CONTRIBUTING.md for guidelines.
For security vulnerabilities, please see our Security Policy.
MIT License - see LICENSE file for details.
Made with ❤️ by the Chaindoc team
FAQs
Server-side SDK for Chaindoc API - document management, signatures, and embedded sessions
We found that @chaindoc_io/server-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket now detects supply chain risks in project manifests, starting with missing lockfiles that can make dependency installs non-reproducible.

Research
/Security News
The trojanized extensions use TinyGo-compiled WebAssembly and Solana transaction memos to resolve command-and-control infrastructure.

Security News
Anthropic says the directive cited national security concerns over a narrow jailbreak, but offered no specific technical details.