🚀. Socket Launch Week Day 2:Introducing Manifest Alerts.Learn more
Sign In

@chaindoc_io/server-sdk

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@chaindoc_io/server-sdk - npm Package Compare versions

Comparing version
2.0.0
to
2.0.1
+8
-0
CHANGELOG.md

@@ -8,2 +8,10 @@ # Changelog

## [2.0.1] - 2026-04-27
### Fixed
- **Email normalization at the SDK boundary.** All email values sent through the SDK are now trimmed and lowercased before reaching the API. Affected inputs: `signatures.createRequest` (`recipients[].email`, `fields[].signerEmail`), `embedded.createSession` (`email`), `contracts.create` (`contragent.email`), `templates.sendForSigning` (`slotAssignments[].email`), `templates.createContract` (`contragent.email`), `documents.create` and `documents.updateRights` (`accessEmails[].email`). Caller-owned input objects are not mutated. Aligns the SDK with the backend rule that `users.email` is canonical lowercase, fixing silent auto-link misses when partner-side emails were stored mixed-case.
---
## [2.0.0] - 2026-04-23

@@ -10,0 +18,0 @@

+1
-1

@@ -1,2 +0,2 @@

"use strict";var D=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var I=Object.prototype.hasOwnProperty;var M=(o,e)=>{for(var t in e)D(o,t,{get:e[t],enumerable:!0})},U=(o,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of A(e))!I.call(o,n)&&n!==t&&D(o,n,{get:()=>e[n],enumerable:!(s=$(e,n))||s.enumerable});return o};var x=o=>U(D({},"__esModule",{value:!0}),o);var K={};M(K,{Chaindoc:()=>w,ChaindocError:()=>u});module.exports=x(K);var u=class extends Error{constructor(t,s,n,c=!1){super(t);this.statusCode=s;this.response=n;this.isRetryable=c;this.name="ChaindocError"}},k={production:"https://api.chaindoc.io",staging:"https://api.chaindoc.io",development:"https://api.chaindoc.io"},L="production",H=3e4,O=3,N=1e3,F=1e4,h=class{baseUrl;secretKey;timeout;defaultHeaders;retryConfig;constructor(e){if(!e.secretKey)throw new u("secretKey is required");if(!e.secretKey.startsWith("sk_"))throw new u('secretKey must start with "sk_"');let t=e.environment??L;this.baseUrl=e.baseUrl??k[t],this.secretKey=e.secretKey,this.timeout=e.timeout??H,this.defaultHeaders={"Content-Type":"application/json",Authorization:`Bearer ${this.secretKey}`,...e.headers},this.retryConfig={maxRetries:e.retry?.maxRetries??O,baseDelayMs:e.retry?.baseDelayMs??N,maxDelayMs:e.retry?.maxDelayMs??F}}getRetryDelay(e){let t=this.retryConfig.baseDelayMs*Math.pow(2,e),s=Math.min(t,this.retryConfig.maxDelayMs),n=s*.25*(Math.random()*2-1);return Math.round(s+n)}isRetryableError(e,t){return t&&t>=500||t===429?!0:e instanceof Error?["ECONNRESET","ECONNREFUSED","ETIMEDOUT","ENOTFOUND","EAI_AGAIN"].some(n=>e.message.includes(n))||e.name==="AbortError":!1}sleep(e){return new Promise(t=>setTimeout(t,e))}async request(e,t={}){let s=`${this.baseUrl}${e}`,n=t.noRetry?1:this.retryConfig.maxRetries+1,c;for(let a=0;a<n;a++){let l=new AbortController,d=setTimeout(()=>l.abort(),t.timeout??this.timeout);try{let i=await fetch(s,{method:t.method??"GET",headers:{...this.defaultHeaders,...t.headers},body:t.body?JSON.stringify(t.body):void 0,signal:l.signal});if(clearTimeout(d),i.status===204||i.headers.get("content-length")==="0")return;let p=i.headers.get("content-type")?.includes("application/json")?await i.json().catch(()=>{}):void 0;if(!i.ok){let m=p&&typeof p=="object"&&"message"in p&&typeof p.message=="string"?p.message:`Request failed with status ${i.status}`,g=this.isRetryableError(null,i.status);if(c=new u(m,i.status,p,g),g&&a<n-1){await this.sleep(this.getRetryDelay(a));continue}throw c}return p}catch(i){if(clearTimeout(d),i instanceof u){if(!i.isRetryable||a>=n-1)throw i;c=i,await this.sleep(this.getRetryDelay(a));continue}let r=this.isRetryableError(i);if(i instanceof Error){let p=i.name==="AbortError"?"Request timeout":i.message;if(c=new u(p,void 0,void 0,r),r&&a<n-1){await this.sleep(this.getRetryDelay(a));continue}throw c}throw new u("Unknown error occurred")}}throw c??new u("Request failed after retries")}async get(e,t){return this.request(e,{...t,method:"GET"})}async post(e,t,s){return this.request(e,{...s,method:"POST",body:t})}async put(e,t,s){return this.request(e,{...s,method:"PUT",body:t})}async delete(e,t){return this.request(e,{...t,method:"DELETE"})}async uploadFiles(e,t,s="media"){let n=this.retryConfig.maxRetries+1,c;for(let a=0;a<n;a++){let l=new FormData;t.forEach(r=>{l.append(s,r)});let d=new AbortController,i=setTimeout(()=>d.abort(),this.timeout*2);try{let r=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:{Authorization:`Bearer ${this.secretKey}`},body:l,signal:d.signal});if(clearTimeout(i),r.status===204||r.headers.get("content-length")==="0")return;let m=r.headers.get("content-type")?.includes("application/json")?await r.json().catch(()=>{}):void 0;if(!r.ok){let g=m&&typeof m=="object"&&"message"in m&&typeof m.message=="string"?m.message:`Upload failed with status ${r.status}`,q=this.isRetryableError(null,r.status);if(c=new u(g,r.status,m,q),q&&a<n-1){await this.sleep(this.getRetryDelay(a));continue}throw c}return m}catch(r){if(clearTimeout(i),r instanceof u){if(!r.isRetryable||a>=n-1)throw r;c=r,await this.sleep(this.getRetryDelay(a));continue}let p=this.isRetryableError(r);if(r instanceof Error){let m=r.name==="AbortError"?"Upload timeout":r.message;if(c=new u(m,void 0,void 0,p),p&&a<n-1){await this.sleep(this.getRetryDelay(a));continue}throw c}throw new u("Unknown error occurred")}}throw c??new u("Upload failed after retries")}};var y=class{constructor(e){this.client=e}async create(e){return this.client.post("/api/v1/documents",e)}async update(e,t){return this.client.put(`/api/v1/documents/${e}`,t)}async updateRights(e,t){return this.client.put(`/api/v1/documents/${e}/rights`,t)}async verify(e){return this.client.post("/api/v1/documents/verify",e)}async getVerificationStatus(e){return this.client.get(`/api/v1/documents/versions/${e}/verification`)}};var R=class{constructor(e){this.client=e}async createRequest(e){return this.client.post("/api/v1/signatures/requests",{...e,deadline:e.deadline.toISOString()})}async getRequestStatus(e){return this.client.get(`/api/v1/signatures/requests/${e}/status`)}async getMyRequests(e){let t=new URLSearchParams;e?.pageNumber&&t.set("pageNumber",String(e.pageNumber)),e?.pageSize&&t.set("pageSize",String(e.pageSize));let s=t.toString();return this.client.get(`/api/v1/signatures/requests${s?`?${s}`:""}`)}async sign(e){return this.client.post("/api/v1/signatures/sign",e)}async getSignatures(e){let t=new URLSearchParams;e?.pageNumber&&t.set("pageNumber",String(e.pageNumber)),e?.pageSize&&t.set("pageSize",String(e.pageSize));let s=t.toString();return this.client.get(`/api/v1/signatures${s?`?${s}`:""}`)}};var f=class{constructor(e){this.client=e}async create(e){return this.client.post("/api/v1/contracts",e)}async list(e){let t=new URLSearchParams;e?.page&&t.set("page",String(e.page)),e?.limit&&t.set("limit",String(e.limit)),e?.status&&t.set("status",e.status),e?.search&&t.set("search",e.search);let s=t.toString();return this.client.get(`/api/v1/contracts${s?`?${s}`:""}`)}async get(e){return this.client.get(`/api/v1/contracts/${e}`)}async getStatus(e){return this.client.get(`/api/v1/contracts/${e}/status`)}async getActivities(e,t){let s=new URLSearchParams;t?.page&&s.set("page",String(t.page)),t?.limit&&s.set("limit",String(t.limit));let n=s.toString();return this.client.get(`/api/v1/contracts/${e}/activities${n?`?${n}`:""}`)}async addPaymentSetup(e,t){return this.client.post(`/api/v1/contracts/${e}/payment-setup`,t)}async send(e,t){return this.client.post(`/api/v1/contracts/${e}/send`,{...t,deadline:t?.deadline?.toISOString()})}async cancel(e){return this.client.post(`/api/v1/contracts/${e}/cancel`,{})}async terminate(e,t){return this.client.post(`/api/v1/contracts/${e}/terminate`,t??{})}};var v=class{constructor(e){this.client=e}async createDocument(e,t){return this.client.post(`/api/v1/templates/${e}/documents`,t)}async sendForSigning(e,t){return this.client.post(`/api/v1/templates/${e}/signature-requests`,t)}async createContract(e,t){return this.client.post(`/api/v1/templates/${e}/contracts`,t)}};var P=class{constructor(e){this.client=e}async create(e,t){return this.client.post(`/api/v1/contracts/${e}/invoices`,t)}async list(e,t){let s=new URLSearchParams;t?.page&&s.set("page",String(t.page)),t?.limit&&s.set("limit",String(t.limit)),t?.status&&s.set("status",t.status),t?.type&&s.set("type",t.type),typeof t?.overdue=="boolean"&&s.set("overdue",String(t.overdue)),t?.dueDateFrom&&s.set("dueDateFrom",t.dueDateFrom),t?.dueDateTo&&s.set("dueDateTo",t.dueDateTo);let n=s.toString();return this.client.get(`/api/v1/contracts/${e}/invoices${n?`?${n}`:""}`)}async get(e,t){return this.client.get(`/api/v1/contracts/${e}/invoices/${t}`)}async send(e,t,s){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/send`,s??{})}async charge(e,t){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/charge`,{})}async markPaid(e,t,s){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/mark-paid`,s??{})}};var C=class{constructor(e){this.client=e}async listByContract(e){return this.client.get(`/api/v1/contracts/${e}/transactions`)}async get(e){return this.client.get(`/api/v1/transactions/${e}`)}};var S=class{constructor(e){this.client=e}async createSession(e){return this.client.post("/api/v1/embedded/sessions",e)}};var T=class{constructor(e){this.client=e}async upload(e){return this.client.uploadFiles("/api/v1/media/upload",e)}};var E=require("crypto"),_=300*1e3,b=class{static verify(e,t,s,n){if(!e||!t||!s||!n)return{valid:!1};let c=new Date(s).getTime();if(isNaN(c))return{valid:!1};if(Math.abs(Date.now()-c)>_)return{valid:!1};let l=t.match(/^v1=([a-f0-9]+)$/i);if(!l||!l[1])return{valid:!1};let d=l[1],i=`${s}.${e}`,r=(0,E.createHmac)("sha256",n).update(i).digest("hex");if(d.length!==r.length)return{valid:!1};let p=Buffer.from(d,"hex"),m=Buffer.from(r,"hex");if(p.length!==m.length)return{valid:!1};if(!(0,E.timingSafeEqual)(p,m))return{valid:!1};try{return{valid:!0,envelope:JSON.parse(e)}}catch{return{valid:!1}}}static parse(e){return JSON.parse(e)}};var w=class{client;static webhooks=b;documents;signatures;contracts;templates;invoices;transactions;embedded;media;constructor(e){this.client=new h(e),this.documents=new y(this.client),this.signatures=new R(this.client),this.contracts=new f(this.client),this.templates=new v(this.client),this.invoices=new P(this.client),this.transactions=new C(this.client),this.embedded=new S(this.client),this.media=new T(this.client)}async getApiKeyInfo(){return this.client.get("/api/v1/me")}async healthCheck(){return this.client.get("/api/v1/health")}};0&&(module.exports={Chaindoc,ChaindocError});
"use strict";var A=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var N=(n,e)=>{for(var t in e)A(n,t,{get:e[t],enumerable:!0})},k=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of U(e))!L.call(n,i)&&i!==t&&A(n,i,{get:()=>e[i],enumerable:!(s=M(e,i))||s.enumerable});return n};var H=n=>k(A({},"__esModule",{value:!0}),n);var j={};N(j,{Chaindoc:()=>D,ChaindocError:()=>p});module.exports=H(j);var p=class extends Error{constructor(t,s,i,c=!1){super(t);this.statusCode=s;this.response=i;this.isRetryable=c;this.name="ChaindocError"}},O={production:"https://api.chaindoc.io",staging:"https://api.chaindoc.io",development:"https://api.chaindoc.io"},z="production",F=3e4,_=3,K=1e3,V=1e4,y=class{baseUrl;secretKey;timeout;defaultHeaders;retryConfig;constructor(e){if(!e.secretKey)throw new p("secretKey is required");if(!e.secretKey.startsWith("sk_"))throw new p('secretKey must start with "sk_"');let t=e.environment??z;this.baseUrl=e.baseUrl??O[t],this.secretKey=e.secretKey,this.timeout=e.timeout??F,this.defaultHeaders={"Content-Type":"application/json",Authorization:`Bearer ${this.secretKey}`,...e.headers},this.retryConfig={maxRetries:e.retry?.maxRetries??_,baseDelayMs:e.retry?.baseDelayMs??K,maxDelayMs:e.retry?.maxDelayMs??V}}getRetryDelay(e){let t=this.retryConfig.baseDelayMs*Math.pow(2,e),s=Math.min(t,this.retryConfig.maxDelayMs),i=s*.25*(Math.random()*2-1);return Math.round(s+i)}isRetryableError(e,t){return t&&t>=500||t===429?!0:e instanceof Error?["ECONNRESET","ECONNREFUSED","ETIMEDOUT","ENOTFOUND","EAI_AGAIN"].some(i=>e.message.includes(i))||e.name==="AbortError":!1}sleep(e){return new Promise(t=>setTimeout(t,e))}async request(e,t={}){let s=`${this.baseUrl}${e}`,i=t.noRetry?1:this.retryConfig.maxRetries+1,c;for(let a=0;a<i;a++){let u=new AbortController,g=setTimeout(()=>u.abort(),t.timeout??this.timeout);try{let o=await fetch(s,{method:t.method??"GET",headers:{...this.defaultHeaders,...t.headers},body:t.body?JSON.stringify(t.body):void 0,signal:u.signal});if(clearTimeout(g),o.status===204||o.headers.get("content-length")==="0")return;let m=o.headers.get("content-type")?.includes("application/json")?await o.json().catch(()=>{}):void 0;if(!o.ok){let l=m&&typeof m=="object"&&"message"in m&&typeof m.message=="string"?m.message:`Request failed with status ${o.status}`,h=this.isRetryableError(null,o.status);if(c=new p(l,o.status,m,h),h&&a<i-1){await this.sleep(this.getRetryDelay(a));continue}throw c}return m}catch(o){if(clearTimeout(g),o instanceof p){if(!o.isRetryable||a>=i-1)throw o;c=o,await this.sleep(this.getRetryDelay(a));continue}let r=this.isRetryableError(o);if(o instanceof Error){let m=o.name==="AbortError"?"Request timeout":o.message;if(c=new p(m,void 0,void 0,r),r&&a<i-1){await this.sleep(this.getRetryDelay(a));continue}throw c}throw new p("Unknown error occurred")}}throw c??new p("Request failed after retries")}async get(e,t){return this.request(e,{...t,method:"GET"})}async post(e,t,s){return this.request(e,{...s,method:"POST",body:t})}async put(e,t,s){return this.request(e,{...s,method:"PUT",body:t})}async delete(e,t){return this.request(e,{...t,method:"DELETE"})}async uploadFiles(e,t,s="media"){let i=this.retryConfig.maxRetries+1,c;for(let a=0;a<i;a++){let u=new FormData;t.forEach(r=>{u.append(s,r)});let g=new AbortController,o=setTimeout(()=>g.abort(),this.timeout*2);try{let r=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:{Authorization:`Bearer ${this.secretKey}`},body:u,signal:g.signal});if(clearTimeout(o),r.status===204||r.headers.get("content-length")==="0")return;let l=r.headers.get("content-type")?.includes("application/json")?await r.json().catch(()=>{}):void 0;if(!r.ok){let h=l&&typeof l=="object"&&"message"in l&&typeof l.message=="string"?l.message:`Upload failed with status ${r.status}`,q=this.isRetryableError(null,r.status);if(c=new p(h,r.status,l,q),q&&a<i-1){await this.sleep(this.getRetryDelay(a));continue}throw c}return l}catch(r){if(clearTimeout(o),r instanceof p){if(!r.isRetryable||a>=i-1)throw r;c=r,await this.sleep(this.getRetryDelay(a));continue}let m=this.isRetryableError(r);if(r instanceof Error){let l=r.name==="AbortError"?"Upload timeout":r.message;if(c=new p(l,void 0,void 0,m),m&&a<i-1){await this.sleep(this.getRetryDelay(a));continue}throw c}throw new p("Unknown error occurred")}}throw c??new p("Upload failed after retries")}};function $(n){return typeof n!="string"?n:n.trim().toLowerCase()}function d(n){return typeof n.email!="string"?{...n}:{...n,email:n.email.trim().toLowerCase()}}function x(n){return typeof n.signerEmail!="string"?{...n}:{...n,signerEmail:n.signerEmail.trim().toLowerCase()}}function I(n){return n?.map(d)}var f=class{constructor(e){this.client=e}async create(e){return this.client.post("/api/v1/documents",{...e,accessEmails:I(e.accessEmails)})}async update(e,t){return this.client.put(`/api/v1/documents/${e}`,t)}async updateRights(e,t){return this.client.put(`/api/v1/documents/${e}/rights`,{...t,accessEmails:I(t.accessEmails)})}async verify(e){return this.client.post("/api/v1/documents/verify",e)}async getVerificationStatus(e){return this.client.get(`/api/v1/documents/versions/${e}/verification`)}};var R=class{constructor(e){this.client=e}async createRequest(e){return this.client.post("/api/v1/signatures/requests",{...e,recipients:e.recipients.map(d),fields:e.fields?.map(x),deadline:e.deadline.toISOString()})}async getRequestStatus(e){return this.client.get(`/api/v1/signatures/requests/${e}/status`)}async getMyRequests(e){let t=new URLSearchParams;e?.pageNumber&&t.set("pageNumber",String(e.pageNumber)),e?.pageSize&&t.set("pageSize",String(e.pageSize));let s=t.toString();return this.client.get(`/api/v1/signatures/requests${s?`?${s}`:""}`)}async sign(e){return this.client.post("/api/v1/signatures/sign",e)}async getSignatures(e){let t=new URLSearchParams;e?.pageNumber&&t.set("pageNumber",String(e.pageNumber)),e?.pageSize&&t.set("pageSize",String(e.pageSize));let s=t.toString();return this.client.get(`/api/v1/signatures${s?`?${s}`:""}`)}};var v=class{constructor(e){this.client=e}async create(e){return this.client.post("/api/v1/contracts",{...e,contragent:d(e.contragent)})}async list(e){let t=new URLSearchParams;e?.page&&t.set("page",String(e.page)),e?.limit&&t.set("limit",String(e.limit)),e?.status&&t.set("status",e.status),e?.search&&t.set("search",e.search);let s=t.toString();return this.client.get(`/api/v1/contracts${s?`?${s}`:""}`)}async get(e){return this.client.get(`/api/v1/contracts/${e}`)}async getStatus(e){return this.client.get(`/api/v1/contracts/${e}/status`)}async getActivities(e,t){let s=new URLSearchParams;t?.page&&s.set("page",String(t.page)),t?.limit&&s.set("limit",String(t.limit));let i=s.toString();return this.client.get(`/api/v1/contracts/${e}/activities${i?`?${i}`:""}`)}async addPaymentSetup(e,t){return this.client.post(`/api/v1/contracts/${e}/payment-setup`,t)}async send(e,t){return this.client.post(`/api/v1/contracts/${e}/send`,{...t,deadline:t?.deadline?.toISOString()})}async cancel(e){return this.client.post(`/api/v1/contracts/${e}/cancel`,{})}async terminate(e,t){return this.client.post(`/api/v1/contracts/${e}/terminate`,t??{})}};var P=class{constructor(e){this.client=e}async createDocument(e,t){return this.client.post(`/api/v1/templates/${e}/documents`,t)}async sendForSigning(e,t){return this.client.post(`/api/v1/templates/${e}/signature-requests`,{...t,slotAssignments:t.slotAssignments.map(d)})}async createContract(e,t){return this.client.post(`/api/v1/templates/${e}/contracts`,{...t,contragent:d(t.contragent)})}};var C=class{constructor(e){this.client=e}async create(e,t){return this.client.post(`/api/v1/contracts/${e}/invoices`,t)}async list(e,t){let s=new URLSearchParams;t?.page&&s.set("page",String(t.page)),t?.limit&&s.set("limit",String(t.limit)),t?.status&&s.set("status",t.status),t?.type&&s.set("type",t.type),typeof t?.overdue=="boolean"&&s.set("overdue",String(t.overdue)),t?.dueDateFrom&&s.set("dueDateFrom",t.dueDateFrom),t?.dueDateTo&&s.set("dueDateTo",t.dueDateTo);let i=s.toString();return this.client.get(`/api/v1/contracts/${e}/invoices${i?`?${i}`:""}`)}async get(e,t){return this.client.get(`/api/v1/contracts/${e}/invoices/${t}`)}async send(e,t,s){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/send`,s??{})}async charge(e,t){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/charge`,{})}async markPaid(e,t,s){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/mark-paid`,s??{})}};var T=class{constructor(e){this.client=e}async listByContract(e){return this.client.get(`/api/v1/contracts/${e}/transactions`)}async get(e){return this.client.get(`/api/v1/transactions/${e}`)}};var S=class{constructor(e){this.client=e}async createSession(e){return this.client.post("/api/v1/embedded/sessions",{...e,email:$(e.email)})}};var E=class{constructor(e){this.client=e}async upload(e){return this.client.uploadFiles("/api/v1/media/upload",e)}};var w=require("crypto"),G=300*1e3,b=class{static verify(e,t,s,i){if(!e||!t||!s||!i)return{valid:!1};let c=new Date(s).getTime();if(isNaN(c))return{valid:!1};if(Math.abs(Date.now()-c)>G)return{valid:!1};let u=t.match(/^v1=([a-f0-9]+)$/i);if(!u||!u[1])return{valid:!1};let g=u[1],o=`${s}.${e}`,r=(0,w.createHmac)("sha256",i).update(o).digest("hex");if(g.length!==r.length)return{valid:!1};let m=Buffer.from(g,"hex"),l=Buffer.from(r,"hex");if(m.length!==l.length)return{valid:!1};if(!(0,w.timingSafeEqual)(m,l))return{valid:!1};try{return{valid:!0,envelope:JSON.parse(e)}}catch{return{valid:!1}}}static parse(e){return JSON.parse(e)}};var D=class{client;static webhooks=b;documents;signatures;contracts;templates;invoices;transactions;embedded;media;constructor(e){this.client=new y(e),this.documents=new f(this.client),this.signatures=new R(this.client),this.contracts=new v(this.client),this.templates=new P(this.client),this.invoices=new C(this.client),this.transactions=new T(this.client),this.embedded=new S(this.client),this.media=new E(this.client)}async getApiKeyInfo(){return this.client.get("/api/v1/me")}async healthCheck(){return this.client.get("/api/v1/health")}};0&&(module.exports={Chaindoc,ChaindocError});
//# sourceMappingURL=index.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/modules/documents.ts","../src/modules/signatures.ts","../src/modules/contracts.ts","../src/modules/templates.ts","../src/modules/invoices.ts","../src/modules/transactions.ts","../src/modules/embedded.ts","../src/modules/media.ts","../src/modules/webhooks.ts","../src/chaindoc.ts"],"sourcesContent":["/**\n * @chaindoc_io/server-sdk\n *\n * Server-side SDK for Chaindoc API\n *\n * @packageDocumentation\n */\n\nexport { Chaindoc } from \"./chaindoc\";\nexport { ChaindocError } from \"./client\";\nexport * from \"./types\";\n","/**\n * HTTP Client for Chaindoc API\n * Uses native fetch (Node 18+)\n */\n\nimport type { ChaindocConfig, ChaindocEnvironment, RetryConfig } from \"./types\";\n\nexport class ChaindocError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public response?: unknown,\n public isRetryable: boolean = false\n ) {\n super(message);\n this.name = \"ChaindocError\";\n }\n}\n\nexport interface RequestOptions {\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n body?: unknown;\n headers?: Record<string, string>;\n timeout?: number;\n /** Disable retry for this specific request */\n noRetry?: boolean;\n}\n\nconst ENVIRONMENT_URLS: Record<ChaindocEnvironment, string> = {\n production: \"https://api.chaindoc.io\",\n staging: \"https://api.chaindoc.io\",\n development: \"https://api.chaindoc.io\",\n};\n\nconst DEFAULT_ENVIRONMENT: ChaindocEnvironment = \"production\";\nconst DEFAULT_TIMEOUT = 30000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_BASE_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 10000;\n\nexport class HttpClient {\n private baseUrl: string;\n private secretKey: string;\n private timeout: number;\n private defaultHeaders: Record<string, string>;\n private retryConfig: Required<RetryConfig>;\n\n constructor(config: ChaindocConfig) {\n if (!config.secretKey) {\n throw new ChaindocError(\"secretKey is required\");\n }\n\n if (!config.secretKey.startsWith(\"sk_\")) {\n throw new ChaindocError('secretKey must start with \"sk_\"');\n }\n\n const environment = config.environment ?? DEFAULT_ENVIRONMENT;\n this.baseUrl = config.baseUrl ?? ENVIRONMENT_URLS[environment];\n this.secretKey = config.secretKey;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n this.defaultHeaders = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.secretKey}`,\n ...config.headers,\n };\n this.retryConfig = {\n maxRetries: config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES,\n baseDelayMs: config.retry?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS,\n maxDelayMs: config.retry?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS,\n };\n }\n\n /**\n * Calculate delay with exponential backoff and jitter\n */\n private getRetryDelay(attempt: number): number {\n const exponentialDelay =\n this.retryConfig.baseDelayMs * Math.pow(2, attempt);\n const cappedDelay = Math.min(exponentialDelay, this.retryConfig.maxDelayMs);\n // Add jitter (±25%)\n const jitter = cappedDelay * 0.25 * (Math.random() * 2 - 1);\n return Math.round(cappedDelay + jitter);\n }\n\n /**\n * Check if error is retryable\n */\n private isRetryableError(error: unknown, statusCode?: number): boolean {\n // Retry on 5xx server errors\n if (statusCode && statusCode >= 500) {\n return true;\n }\n // Retry on 429 Too Many Requests\n if (statusCode === 429) {\n return true;\n }\n // Retry on network errors\n if (error instanceof Error) {\n const networkErrors = [\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n \"ETIMEDOUT\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n ];\n return (\n networkErrors.some((e) => error.message.includes(e)) ||\n error.name === \"AbortError\"\n );\n }\n return false;\n }\n\n /**\n * Sleep for specified milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n async request<T>(endpoint: string, options: RequestOptions = {}): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n const maxAttempts = options.noRetry ? 1 : this.retryConfig.maxRetries + 1;\n let lastError: ChaindocError | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n options.timeout ?? this.timeout\n );\n\n try {\n const response = await fetch(url, {\n method: options.method ?? \"GET\",\n headers: {\n ...this.defaultHeaders,\n ...options.headers,\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Handle empty responses (204 No Content, empty body)\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return undefined as T;\n }\n\n // Only parse JSON if content-type indicates JSON\n const contentType = response.headers.get(\"content-type\");\n const data: unknown = contentType?.includes(\"application/json\")\n ? await response.json().catch(() => undefined)\n : undefined;\n\n if (!response.ok) {\n const errorMessage =\n data &&\n typeof data === \"object\" &&\n \"message\" in data &&\n typeof data.message === \"string\"\n ? data.message\n : `Request failed with status ${response.status}`;\n const isRetryable = this.isRetryableError(null, response.status);\n lastError = new ChaindocError(\n errorMessage,\n response.status,\n data,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n return data as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ChaindocError) {\n if (!error.isRetryable || attempt >= maxAttempts - 1) {\n throw error;\n }\n lastError = error;\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n const isRetryable = this.isRetryableError(error);\n if (error instanceof Error) {\n const message =\n error.name === \"AbortError\" ? \"Request timeout\" : error.message;\n lastError = new ChaindocError(\n message,\n undefined,\n undefined,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n throw new ChaindocError(\"Unknown error occurred\");\n }\n }\n\n throw lastError ?? new ChaindocError(\"Request failed after retries\");\n }\n\n async get<T>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"GET\" });\n }\n\n async post<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"POST\", body });\n }\n\n async put<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"PUT\", body });\n }\n\n async delete<T>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"DELETE\" });\n }\n\n /**\n * Upload files using multipart/form-data\n *\n * @remarks Requires Node.js >= 18 (uses native File, Blob, FormData APIs)\n */\n async uploadFiles<T>(\n endpoint: string,\n files: File[] | Blob[],\n fieldName = \"media\"\n ): Promise<T> {\n const maxAttempts = this.retryConfig.maxRetries + 1;\n let lastError: ChaindocError | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const formData = new FormData();\n files.forEach((file) => {\n formData.append(fieldName, file);\n });\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout * 2);\n\n try {\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.secretKey}`,\n },\n body: formData,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return undefined as T;\n }\n\n const contentType = response.headers.get(\"content-type\");\n const data: unknown = contentType?.includes(\"application/json\")\n ? await response.json().catch(() => undefined)\n : undefined;\n\n if (!response.ok) {\n const errorMessage =\n data &&\n typeof data === \"object\" &&\n \"message\" in data &&\n typeof data.message === \"string\"\n ? data.message\n : `Upload failed with status ${response.status}`;\n const isRetryable = this.isRetryableError(null, response.status);\n lastError = new ChaindocError(\n errorMessage,\n response.status,\n data,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n return data as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ChaindocError) {\n if (!error.isRetryable || attempt >= maxAttempts - 1) {\n throw error;\n }\n lastError = error;\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n const isRetryable = this.isRetryableError(error);\n if (error instanceof Error) {\n const message =\n error.name === \"AbortError\" ? \"Upload timeout\" : error.message;\n lastError = new ChaindocError(\n message,\n undefined,\n undefined,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n throw new ChaindocError(\"Unknown error occurred\");\n }\n }\n\n throw lastError ?? new ChaindocError(\"Upload failed after retries\");\n }\n}\n","/**\n * Documents Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateDocumentParams,\n UpdateDocumentParams,\n UpdateDocumentRightsParams,\n DocumentResponse,\n VerifyDocumentParams,\n VerifyDocumentResponse,\n} from '../types';\n\nexport class Documents {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a new document\n * Creates document with first version. Set status to \"published\" to verify in blockchain immediately.\n */\n async create(params: CreateDocumentParams): Promise<DocumentResponse> {\n return this.client.post<DocumentResponse>('/api/v1/documents', params);\n }\n\n /**\n * Update document (creates new version)\n * Set status to \"published\" to verify in blockchain.\n */\n async update(documentId: string, params: UpdateDocumentParams): Promise<DocumentResponse> {\n return this.client.put<DocumentResponse>(`/api/v1/documents/${documentId}`, params);\n }\n\n /**\n * Update document access rights\n */\n async updateRights(documentId: string, params: UpdateDocumentRightsParams): Promise<DocumentResponse> {\n return this.client.put<DocumentResponse>(`/api/v1/documents/${documentId}/rights`, params);\n }\n\n /**\n * Verify document in blockchain\n */\n async verify(params: VerifyDocumentParams): Promise<VerifyDocumentResponse> {\n return this.client.post<VerifyDocumentResponse>('/api/v1/documents/verify', params);\n }\n\n /**\n * Get verification status for a document version\n */\n async getVerificationStatus(versionId: string): Promise<VerifyDocumentResponse> {\n return this.client.get<VerifyDocumentResponse>(`/api/v1/documents/versions/${versionId}/verification`);\n }\n}\n","/**\n * Signatures Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateSignatureRequestParams,\n SignDocumentParams,\n SignatureRequestResponse,\n SignatureRequestStatus,\n PaginationParams,\n GetMyRequestsResponse,\n GetSignaturesResponse,\n} from '../types';\n\nexport class Signatures {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a signature request\n *\n * When embeddedFlow=true and isKycRequired=true:\n * - Signers complete KYC inside Chaindoc before signing\n * - Backend enforces KYC at signing time\n */\n async createRequest(params: CreateSignatureRequestParams): Promise<SignatureRequestResponse> {\n return this.client.post<SignatureRequestResponse>('/api/v1/signatures/requests', {\n ...params,\n deadline: params.deadline.toISOString(),\n });\n }\n\n /**\n * Get signature request status\n */\n async getRequestStatus(requestId: string): Promise<SignatureRequestStatus> {\n return this.client.get<SignatureRequestStatus>(`/api/v1/signatures/requests/${requestId}/status`);\n }\n\n /**\n * Get all signature requests for current user\n */\n async getMyRequests(pagination?: PaginationParams): Promise<GetMyRequestsResponse> {\n const params = new URLSearchParams();\n if (pagination?.pageNumber) params.set('pageNumber', String(pagination.pageNumber));\n if (pagination?.pageSize) params.set('pageSize', String(pagination.pageSize));\n\n const query = params.toString();\n return this.client.get<GetMyRequestsResponse>(`/api/v1/signatures/requests${query ? `?${query}` : ''}`);\n }\n\n /**\n * Sign a document\n * API key owner must be one of the signatories.\n */\n async sign(params: SignDocumentParams): Promise<{ success: boolean; requestId: string; signedAt: string; message: string }> {\n return this.client.post('/api/v1/signatures/sign', params);\n }\n\n /**\n * Get user's signatures (signature requests where user is a signer)\n */\n async getSignatures(pagination?: PaginationParams): Promise<GetSignaturesResponse> {\n const params = new URLSearchParams();\n if (pagination?.pageNumber) params.set('pageNumber', String(pagination.pageNumber));\n if (pagination?.pageSize) params.set('pageSize', String(pagination.pageSize));\n\n const query = params.toString();\n return this.client.get<GetSignaturesResponse>(`/api/v1/signatures${query ? `?${query}` : ''}`);\n }\n}\n","/**\n * Contracts Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateContractParams,\n ContractResponse,\n ContractListResponse,\n ContractStatusResponse,\n ContractActivitiesResponse,\n PaymentSetupParams,\n TerminateContractParams,\n ContractActionResponse,\n ContractSendResponse,\n ContractSendParams,\n ContractListParams,\n PaginationParams,\n} from '../types';\n\nexport class Contracts {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a new contract\n * Creates a contract in DRAFT status with a document and contragent info.\n * Payment terms can be included or added later via addPaymentSetup().\n */\n async create(params: CreateContractParams): Promise<ContractResponse> {\n return this.client.post<ContractResponse>('/api/v1/contracts', params);\n }\n\n /**\n * List contracts\n * Returns paginated list of contracts with optional filters.\n */\n async list(params?: ContractListParams): Promise<ContractListResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n if (params?.status) query.set('status', params.status);\n if (params?.search) query.set('search', params.search);\n\n const qs = query.toString();\n return this.client.get<ContractListResponse>(`/api/v1/contracts${qs ? `?${qs}` : ''}`);\n }\n\n /**\n * Get contract details\n * Returns full contract details including payment terms and signing status.\n */\n async get(contractId: string): Promise<ContractResponse> {\n return this.client.get<ContractResponse>(`/api/v1/contracts/${contractId}`);\n }\n\n /**\n * Get contract lifecycle status\n * Returns lightweight status summary including signing progress and payment overview.\n */\n async getStatus(contractId: string): Promise<ContractStatusResponse> {\n return this.client.get<ContractStatusResponse>(`/api/v1/contracts/${contractId}/status`);\n }\n\n /**\n * Get contract activity log\n * Returns paginated activity log for the contract.\n */\n async getActivities(contractId: string, params?: PaginationParams): Promise<ContractActivitiesResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n\n const qs = query.toString();\n return this.client.get<ContractActivitiesResponse>(\n `/api/v1/contracts/${contractId}/activities${qs ? `?${qs}` : ''}`\n );\n }\n\n /**\n * Add payment terms to a contract\n * Adds payment terms to a DRAFT contract that was created without them.\n */\n async addPaymentSetup(contractId: string, params: PaymentSetupParams): Promise<ContractResponse> {\n return this.client.post<ContractResponse>(`/api/v1/contracts/${contractId}/payment-setup`, params);\n }\n\n /**\n * Send contract for signing\n * Initiates the signing flow for a DRAFT contract.\n */\n async send(contractId: string, params?: ContractSendParams): Promise<ContractSendResponse> {\n return this.client.post<ContractSendResponse>(`/api/v1/contracts/${contractId}/send`, {\n ...params,\n deadline: params?.deadline?.toISOString(),\n });\n }\n\n /**\n * Cancel contract\n * Cancels a DRAFT contract.\n */\n async cancel(contractId: string): Promise<ContractActionResponse> {\n return this.client.post<ContractActionResponse>(`/api/v1/contracts/${contractId}/cancel`, {});\n }\n\n /**\n * Terminate contract\n * Initiates termination for an ACTIVE contract.\n * For ONE_SIDE: terminates immediately.\n * For MUTUAL_APPROVAL: creates termination request pending counterparty approval.\n */\n async terminate(contractId: string, params?: TerminateContractParams): Promise<ContractActionResponse> {\n return this.client.post<ContractActionResponse>(\n `/api/v1/contracts/${contractId}/terminate`,\n params ?? {}\n );\n }\n}\n","/**\n * Templates Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateContractFromTemplateParams,\n CreateDocumentFromTemplateParams,\n CreateTemplateSignatureRequestParams,\n TemplateContractResponse,\n TemplateDocumentResponse,\n TemplateSignatureRequestResponse,\n} from '../types';\n\nexport class Templates {\n constructor(private client: HttpClient) {}\n\n /**\n * Render a published template and create a draft document.\n */\n async createDocument(\n templateId: string,\n params: CreateDocumentFromTemplateParams,\n ): Promise<TemplateDocumentResponse> {\n return this.client.post<TemplateDocumentResponse>(`/api/v1/templates/${templateId}/documents`, params);\n }\n\n /**\n * Render a published template and immediately create a signature request.\n */\n async sendForSigning(\n templateId: string,\n params: CreateTemplateSignatureRequestParams,\n ): Promise<TemplateSignatureRequestResponse> {\n return this.client.post<TemplateSignatureRequestResponse>(\n `/api/v1/templates/${templateId}/signature-requests`,\n params,\n );\n }\n\n /**\n * Render a published template and create a contract with an active signing flow.\n */\n async createContract(\n templateId: string,\n params: CreateContractFromTemplateParams,\n ): Promise<TemplateContractResponse> {\n return this.client.post<TemplateContractResponse>(`/api/v1/templates/${templateId}/contracts`, params);\n }\n}\n","/**\n * Invoices Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateInvoiceParams,\n InvoiceActionResponse,\n InvoiceListParams,\n InvoiceListResponse,\n InvoiceResponse,\n MarkInvoicePaidParams,\n SendInvoiceParams,\n} from '../types';\n\nexport class Invoices {\n constructor(private client: HttpClient) {}\n\n /**\n * Create an invoice for a contract.\n */\n async create(contractId: string, params: CreateInvoiceParams): Promise<InvoiceResponse> {\n return this.client.post<InvoiceResponse>(`/api/v1/contracts/${contractId}/invoices`, params);\n }\n\n /**\n * List invoices for a contract.\n */\n async list(contractId: string, params?: InvoiceListParams): Promise<InvoiceListResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n if (params?.status) query.set('status', params.status);\n if (params?.type) query.set('type', params.type);\n if (typeof params?.overdue === 'boolean') query.set('overdue', String(params.overdue));\n if (params?.dueDateFrom) query.set('dueDateFrom', params.dueDateFrom);\n if (params?.dueDateTo) query.set('dueDateTo', params.dueDateTo);\n\n const qs = query.toString();\n return this.client.get<InvoiceListResponse>(\n `/api/v1/contracts/${contractId}/invoices${qs ? `?${qs}` : ''}`,\n );\n }\n\n /**\n * Get a single invoice by UUID.\n */\n async get(contractId: string, invoiceId: string): Promise<InvoiceResponse> {\n return this.client.get<InvoiceResponse>(`/api/v1/contracts/${contractId}/invoices/${invoiceId}`);\n }\n\n /**\n * Send a draft invoice to the contragent.\n */\n async send(\n contractId: string,\n invoiceId: string,\n params?: SendInvoiceParams,\n ): Promise<InvoiceActionResponse> {\n return this.client.post<InvoiceActionResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/send`,\n params ?? {},\n );\n }\n\n /**\n * Charge the default payment method for the invoice.\n */\n async charge(contractId: string, invoiceId: string): Promise<InvoiceActionResponse> {\n return this.client.post<InvoiceActionResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/charge`,\n {},\n );\n }\n\n /**\n * Mark an invoice as paid for offline/external payments.\n */\n async markPaid(\n contractId: string,\n invoiceId: string,\n params?: MarkInvoicePaidParams,\n ): Promise<InvoiceResponse> {\n return this.client.post<InvoiceResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/mark-paid`,\n params ?? {},\n );\n }\n}\n","/**\n * Transactions Module\n */\n\nimport type { HttpClient } from '../client';\nimport type { TransactionListResponse, TransactionResponse } from '../types';\n\nexport class Transactions {\n constructor(private client: HttpClient) {}\n\n /**\n * List transactions for a contract.\n */\n async listByContract(contractId: string): Promise<TransactionListResponse> {\n return this.client.get<TransactionListResponse>(`/api/v1/contracts/${contractId}/transactions`);\n }\n\n /**\n * Get a single transaction by UUID.\n */\n async get(transactionId: string): Promise<TransactionResponse> {\n return this.client.get<TransactionResponse>(`/api/v1/transactions/${transactionId}`);\n }\n}\n","/**\n * Embedded Sessions Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateEmbeddedSessionParams,\n EmbeddedSessionResponse,\n} from '../types';\n\nexport class Embedded {\n constructor(private client: HttpClient) {}\n\n /**\n * Create an embedded session for document signing\n *\n * - Session is valid for 10 minutes\n * - OTP will be sent to the provided email\n * - Use returned sessionId with @chaindoc_io/embed-sdk on frontend\n *\n * @example\n * ```typescript\n * const session = await chaindoc.embedded.createSession({\n * email: 'signer@example.com',\n * metadata: {\n * documentId: 'doc_xxx',\n * signatureRequestId: 'req_xxx',\n * returnUrl: 'https://yourapp.com/signing-complete',\n * },\n * });\n *\n * // Pass session.sessionId to frontend\n * // Frontend uses: sdk.openSignatureFlow({ sessionId: session.sessionId })\n * ```\n */\n async createSession(params: CreateEmbeddedSessionParams): Promise<EmbeddedSessionResponse> {\n return this.client.post<EmbeddedSessionResponse>('/api/v1/embedded/sessions', params);\n }\n}\n","/**\n * Media Module\n */\n\nimport type { HttpClient } from '../client';\nimport type { MediaUploadResponse } from '../types';\n\nexport class Media {\n constructor(private client: HttpClient) {}\n\n /**\n * Upload media files\n *\n * Supported file types:\n * - Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT\n * - Images: JPG, JPEG, PNG, GIF, WEBP, SVG\n * - Videos: MP4, AVI, MOV, WMV\n *\n * Use returned media object when creating documents.\n *\n * @example\n * ```typescript\n * import { readFile } from 'fs/promises';\n *\n * const buffer = await readFile('./contract.pdf');\n * const file = new Blob([buffer], { type: 'application/pdf' });\n *\n * const { media } = await chaindoc.media.upload([file]);\n *\n * // Use media[0] when creating document\n * await chaindoc.documents.create({\n * name: 'Contract',\n * media: media[0],\n * // ...\n * });\n * ```\n */\n async upload(files: File[] | Blob[]): Promise<MediaUploadResponse> {\n return this.client.uploadFiles<MediaUploadResponse>('/api/v1/media/upload', files);\n }\n}\n","/**\n * Webhook Verification Utilities\n *\n * Helpers for verifying webhook signatures and parsing webhook payloads\n * from the Chaindoc API.\n *\n * @example\n * ```typescript\n * import { Chaindoc } from '@chaindoc_io/server-sdk';\n *\n * // In your webhook handler:\n * const result = Chaindoc.webhooks.verify(rawBody, signature, timestamp, secret);\n *\n * if (result.valid) {\n * console.log('Event:', result.envelope.type);\n * console.log('Data:', result.envelope.data);\n * }\n * ```\n */\n\nimport { createHmac, timingSafeEqual } from \"crypto\";\nimport type { WebhookEnvelope, WebhookVerificationResult } from \"../types\";\n\n/** Maximum age of a webhook delivery before it's considered stale (5 minutes) */\nconst MAX_TIMESTAMP_AGE_MS = 5 * 60 * 1000;\n\nexport class Webhooks {\n /**\n * Verify a webhook signature and parse the envelope.\n *\n * @param rawBody - The raw request body string (NOT parsed JSON)\n * @param signature - Value of the `X-Chaindoc-Signature` header (e.g. \"v1=abc123...\")\n * @param timestamp - Value of the `X-Chaindoc-Timestamp` header (ISO 8601)\n * @param secret - Your webhook secret from the Chaindoc dashboard\n * @returns Verification result with parsed envelope if valid\n */\n static verify(\n rawBody: string,\n signature: string,\n timestamp: string,\n secret: string\n ): WebhookVerificationResult {\n if (!rawBody || !signature || !timestamp || !secret) {\n return { valid: false };\n }\n\n // Check timestamp freshness to prevent replay attacks\n const deliveryTime = new Date(timestamp).getTime();\n if (isNaN(deliveryTime)) {\n return { valid: false };\n }\n\n const age = Math.abs(Date.now() - deliveryTime);\n if (age > MAX_TIMESTAMP_AGE_MS) {\n return { valid: false };\n }\n\n // Extract hex from \"v1=<hex>\" format\n const match = signature.match(/^v1=([a-f0-9]+)$/i);\n if (!match || !match[1]) {\n return { valid: false };\n }\n const receivedHex: string = match[1];\n\n // Compute expected signature: HMAC-SHA256(timestamp.rawBody)\n const signingInput = `${timestamp}.${rawBody}`;\n const expectedHex = createHmac(\"sha256\", secret)\n .update(signingInput)\n .digest(\"hex\");\n\n // Timing-safe comparison\n if (receivedHex.length !== expectedHex.length) {\n return { valid: false };\n }\n\n const a = Buffer.from(receivedHex, \"hex\");\n const b = Buffer.from(expectedHex, \"hex\");\n\n if (a.length !== b.length) {\n return { valid: false };\n }\n\n if (!timingSafeEqual(a, b)) {\n return { valid: false };\n }\n\n // Parse envelope\n try {\n const envelope: WebhookEnvelope = JSON.parse(rawBody);\n return { valid: true, envelope };\n } catch {\n return { valid: false };\n }\n }\n\n /**\n * Parse a webhook body without verifying the signature.\n * Use this only when you trust the transport layer (e.g. internal queue).\n */\n static parse<T = Record<string, unknown>>(\n rawBody: string\n ): WebhookEnvelope<T> {\n return JSON.parse(rawBody);\n }\n}\n","/**\n * Chaindoc Server SDK\n *\n * @example\n * ```typescript\n * import { Chaindoc } from '@chaindoc_io/server-sdk';\n *\n * const chaindoc = new Chaindoc({\n * secretKey: 'sk_your_secret_key',\n * });\n *\n * // Create a document\n * const doc = await chaindoc.documents.create({\n * name: 'Contract',\n * description: 'Service agreement',\n * media: { type: 'document', key: '/path/to/file.pdf' },\n * hashtags: ['#contract'],\n * status: 'published',\n * });\n *\n * // Create signature request\n * const request = await chaindoc.signatures.createRequest({\n * versionId: doc.document.currentVersion.id,\n * recipients: [{ email: 'signer@example.com' }],\n * deadline: new Date('2025-12-31'),\n * embeddedFlow: true,\n * });\n *\n * // Create embedded session for frontend\n * const session = await chaindoc.embedded.createSession({\n * email: 'signer@example.com',\n * metadata: {\n * documentId: doc.documentId,\n * signatureRequestId: request.requestId,\n * },\n * });\n *\n * // Pass session.sessionId to frontend\n * ```\n */\n\nimport { HttpClient } from \"./client\";\nimport { Documents } from \"./modules/documents\";\nimport { Signatures } from \"./modules/signatures\";\nimport { Contracts } from \"./modules/contracts\";\nimport { Templates } from \"./modules/templates\";\nimport { Invoices } from \"./modules/invoices\";\nimport { Transactions } from \"./modules/transactions\";\nimport { Embedded } from \"./modules/embedded\";\nimport { Media } from \"./modules/media\";\nimport { Webhooks } from \"./modules/webhooks\";\nimport type { ChaindocConfig, ApiKeyInfo, HealthCheckResponse } from \"./types\";\n\nexport class Chaindoc {\n private client: HttpClient;\n\n /**\n * Webhook verification utilities (static)\n *\n * @example\n * ```typescript\n * const result = Chaindoc.webhooks.verify(rawBody, signature, timestamp, secret);\n * ```\n */\n public static readonly webhooks = Webhooks;\n\n /**\n * Documents API\n * Create, update, and verify documents\n */\n public readonly documents: Documents;\n\n /**\n * Signatures API\n * Create signature requests and sign documents\n */\n public readonly signatures: Signatures;\n\n /**\n * Contracts API\n * Create, manage, and track contract lifecycle\n */\n public readonly contracts: Contracts;\n\n /**\n * Templates API\n * Use published templates to generate documents, signature requests, and contracts\n */\n public readonly templates: Templates;\n\n /**\n * Invoices API\n * Create, send, charge, and inspect contract invoices\n */\n public readonly invoices: Invoices;\n\n /**\n * Transactions API\n * Inspect payment transactions across contract invoices\n */\n public readonly transactions: Transactions;\n\n /**\n * Embedded Sessions API\n * Create sessions for embedded document signing\n */\n public readonly embedded: Embedded;\n\n /**\n * Media API\n * Upload files for use in documents\n */\n public readonly media: Media;\n\n constructor(config: ChaindocConfig) {\n this.client = new HttpClient(config);\n\n this.documents = new Documents(this.client);\n this.signatures = new Signatures(this.client);\n this.contracts = new Contracts(this.client);\n this.templates = new Templates(this.client);\n this.invoices = new Invoices(this.client);\n this.transactions = new Transactions(this.client);\n this.embedded = new Embedded(this.client);\n this.media = new Media(this.client);\n }\n\n /**\n * Get current API key information\n */\n async getApiKeyInfo(): Promise<ApiKeyInfo> {\n return this.client.get<ApiKeyInfo>(\"/api/v1/me\");\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<HealthCheckResponse> {\n return this.client.get<HealthCheckResponse>(\"/api/v1/health\");\n }\n}\n"],"mappings":"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","names":["index_exports","__export","Chaindoc","ChaindocError","__toCommonJS","ChaindocError","message","statusCode","response","isRetryable","ENVIRONMENT_URLS","DEFAULT_ENVIRONMENT","DEFAULT_TIMEOUT","DEFAULT_MAX_RETRIES","DEFAULT_BASE_DELAY_MS","DEFAULT_MAX_DELAY_MS","HttpClient","config","environment","attempt","exponentialDelay","cappedDelay","jitter","error","e","ms","resolve","endpoint","options","url","maxAttempts","lastError","controller","timeoutId","data","errorMessage","body","files","fieldName","formData","file","Documents","client","params","documentId","versionId","Signatures","client","params","requestId","pagination","query","Contracts","client","params","query","qs","contractId","Templates","client","templateId","params","Invoices","client","contractId","params","query","qs","invoiceId","Transactions","client","contractId","transactionId","Embedded","client","params","Media","client","files","import_crypto","MAX_TIMESTAMP_AGE_MS","Webhooks","rawBody","signature","timestamp","secret","deliveryTime","match","receivedHex","signingInput","expectedHex","a","b","Chaindoc","Webhooks","config","HttpClient","Documents","Signatures","Contracts","Templates","Invoices","Transactions","Embedded","Media"]}
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/utils/normalize-email.ts","../src/modules/documents.ts","../src/modules/signatures.ts","../src/modules/contracts.ts","../src/modules/templates.ts","../src/modules/invoices.ts","../src/modules/transactions.ts","../src/modules/embedded.ts","../src/modules/media.ts","../src/modules/webhooks.ts","../src/chaindoc.ts"],"sourcesContent":["/**\n * @chaindoc_io/server-sdk\n *\n * Server-side SDK for Chaindoc API\n *\n * @packageDocumentation\n */\n\nexport { Chaindoc } from \"./chaindoc\";\nexport { ChaindocError } from \"./client\";\nexport * from \"./types\";\n","/**\n * HTTP Client for Chaindoc API\n * Uses native fetch (Node 18+)\n */\n\nimport type { ChaindocConfig, ChaindocEnvironment, RetryConfig } from \"./types\";\n\nexport class ChaindocError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public response?: unknown,\n public isRetryable: boolean = false\n ) {\n super(message);\n this.name = \"ChaindocError\";\n }\n}\n\nexport interface RequestOptions {\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n body?: unknown;\n headers?: Record<string, string>;\n timeout?: number;\n /** Disable retry for this specific request */\n noRetry?: boolean;\n}\n\nconst ENVIRONMENT_URLS: Record<ChaindocEnvironment, string> = {\n production: \"https://api.chaindoc.io\",\n staging: \"https://api.chaindoc.io\",\n development: \"https://api.chaindoc.io\",\n};\n\nconst DEFAULT_ENVIRONMENT: ChaindocEnvironment = \"production\";\nconst DEFAULT_TIMEOUT = 30000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_BASE_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 10000;\n\nexport class HttpClient {\n private baseUrl: string;\n private secretKey: string;\n private timeout: number;\n private defaultHeaders: Record<string, string>;\n private retryConfig: Required<RetryConfig>;\n\n constructor(config: ChaindocConfig) {\n if (!config.secretKey) {\n throw new ChaindocError(\"secretKey is required\");\n }\n\n if (!config.secretKey.startsWith(\"sk_\")) {\n throw new ChaindocError('secretKey must start with \"sk_\"');\n }\n\n const environment = config.environment ?? DEFAULT_ENVIRONMENT;\n this.baseUrl = config.baseUrl ?? ENVIRONMENT_URLS[environment];\n this.secretKey = config.secretKey;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n this.defaultHeaders = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.secretKey}`,\n ...config.headers,\n };\n this.retryConfig = {\n maxRetries: config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES,\n baseDelayMs: config.retry?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS,\n maxDelayMs: config.retry?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS,\n };\n }\n\n /**\n * Calculate delay with exponential backoff and jitter\n */\n private getRetryDelay(attempt: number): number {\n const exponentialDelay =\n this.retryConfig.baseDelayMs * Math.pow(2, attempt);\n const cappedDelay = Math.min(exponentialDelay, this.retryConfig.maxDelayMs);\n // Add jitter (±25%)\n const jitter = cappedDelay * 0.25 * (Math.random() * 2 - 1);\n return Math.round(cappedDelay + jitter);\n }\n\n /**\n * Check if error is retryable\n */\n private isRetryableError(error: unknown, statusCode?: number): boolean {\n // Retry on 5xx server errors\n if (statusCode && statusCode >= 500) {\n return true;\n }\n // Retry on 429 Too Many Requests\n if (statusCode === 429) {\n return true;\n }\n // Retry on network errors\n if (error instanceof Error) {\n const networkErrors = [\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n \"ETIMEDOUT\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n ];\n return (\n networkErrors.some((e) => error.message.includes(e)) ||\n error.name === \"AbortError\"\n );\n }\n return false;\n }\n\n /**\n * Sleep for specified milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n async request<T>(endpoint: string, options: RequestOptions = {}): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n const maxAttempts = options.noRetry ? 1 : this.retryConfig.maxRetries + 1;\n let lastError: ChaindocError | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n options.timeout ?? this.timeout\n );\n\n try {\n const response = await fetch(url, {\n method: options.method ?? \"GET\",\n headers: {\n ...this.defaultHeaders,\n ...options.headers,\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Handle empty responses (204 No Content, empty body)\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return undefined as T;\n }\n\n // Only parse JSON if content-type indicates JSON\n const contentType = response.headers.get(\"content-type\");\n const data: unknown = contentType?.includes(\"application/json\")\n ? await response.json().catch(() => undefined)\n : undefined;\n\n if (!response.ok) {\n const errorMessage =\n data &&\n typeof data === \"object\" &&\n \"message\" in data &&\n typeof data.message === \"string\"\n ? data.message\n : `Request failed with status ${response.status}`;\n const isRetryable = this.isRetryableError(null, response.status);\n lastError = new ChaindocError(\n errorMessage,\n response.status,\n data,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n return data as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ChaindocError) {\n if (!error.isRetryable || attempt >= maxAttempts - 1) {\n throw error;\n }\n lastError = error;\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n const isRetryable = this.isRetryableError(error);\n if (error instanceof Error) {\n const message =\n error.name === \"AbortError\" ? \"Request timeout\" : error.message;\n lastError = new ChaindocError(\n message,\n undefined,\n undefined,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n throw new ChaindocError(\"Unknown error occurred\");\n }\n }\n\n throw lastError ?? new ChaindocError(\"Request failed after retries\");\n }\n\n async get<T>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"GET\" });\n }\n\n async post<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"POST\", body });\n }\n\n async put<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"PUT\", body });\n }\n\n async delete<T>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"DELETE\" });\n }\n\n /**\n * Upload files using multipart/form-data\n *\n * @remarks Requires Node.js >= 18 (uses native File, Blob, FormData APIs)\n */\n async uploadFiles<T>(\n endpoint: string,\n files: File[] | Blob[],\n fieldName = \"media\"\n ): Promise<T> {\n const maxAttempts = this.retryConfig.maxRetries + 1;\n let lastError: ChaindocError | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const formData = new FormData();\n files.forEach((file) => {\n formData.append(fieldName, file);\n });\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout * 2);\n\n try {\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.secretKey}`,\n },\n body: formData,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return undefined as T;\n }\n\n const contentType = response.headers.get(\"content-type\");\n const data: unknown = contentType?.includes(\"application/json\")\n ? await response.json().catch(() => undefined)\n : undefined;\n\n if (!response.ok) {\n const errorMessage =\n data &&\n typeof data === \"object\" &&\n \"message\" in data &&\n typeof data.message === \"string\"\n ? data.message\n : `Upload failed with status ${response.status}`;\n const isRetryable = this.isRetryableError(null, response.status);\n lastError = new ChaindocError(\n errorMessage,\n response.status,\n data,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n return data as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ChaindocError) {\n if (!error.isRetryable || attempt >= maxAttempts - 1) {\n throw error;\n }\n lastError = error;\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n const isRetryable = this.isRetryableError(error);\n if (error instanceof Error) {\n const message =\n error.name === \"AbortError\" ? \"Upload timeout\" : error.message;\n lastError = new ChaindocError(\n message,\n undefined,\n undefined,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n throw new ChaindocError(\"Unknown error occurred\");\n }\n }\n\n throw lastError ?? new ChaindocError(\"Upload failed after retries\");\n }\n}\n","/**\n * Email normalization helpers.\n *\n * The Chaindoc backend stores `users.email` lowercased, but historically\n * accepted mixed-case input on signer/contragent/recipient fields. To keep\n * partner integrations from silently dropping auto-link matches, every email\n * payload sent through the SDK is trimmed and lowercased before reaching the\n * wire.\n */\n\nexport function normalizeEmail(value: string): string;\nexport function normalizeEmail(value: string | undefined): string | undefined;\nexport function normalizeEmail(value: string | null): string | null;\nexport function normalizeEmail(value: string | null | undefined): string | null | undefined;\nexport function normalizeEmail(\n value: string | null | undefined,\n): string | null | undefined {\n if (typeof value !== 'string') return value;\n return value.trim().toLowerCase();\n}\n\n/**\n * Returns a shallow copy of `input` with `email` normalized. Leaves the source\n * object untouched so callers can keep using the value they passed in.\n */\nexport function withNormalizedEmail<T extends { email?: string | null | undefined }>(\n input: T,\n): T {\n if (typeof input.email !== 'string') return { ...input };\n return { ...input, email: input.email.trim().toLowerCase() };\n}\n\n/**\n * Returns a shallow copy of `input` with `signerEmail` normalized.\n */\nexport function withNormalizedSignerEmail<\n T extends { signerEmail?: string | null | undefined },\n>(input: T): T {\n if (typeof input.signerEmail !== 'string') return { ...input };\n return { ...input, signerEmail: input.signerEmail.trim().toLowerCase() };\n}\n","/**\n * Documents Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n AccessEmail,\n CreateDocumentParams,\n UpdateDocumentParams,\n UpdateDocumentRightsParams,\n DocumentResponse,\n VerifyDocumentParams,\n VerifyDocumentResponse,\n} from '../types';\nimport { withNormalizedEmail } from '../utils/normalize-email';\n\nfunction normalizeAccessEmails(accessEmails: AccessEmail[] | undefined): AccessEmail[] | undefined {\n return accessEmails?.map(withNormalizedEmail);\n}\n\nexport class Documents {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a new document\n * Creates document with first version. Set status to \"published\" to verify in blockchain immediately.\n */\n async create(params: CreateDocumentParams): Promise<DocumentResponse> {\n return this.client.post<DocumentResponse>('/api/v1/documents', {\n ...params,\n accessEmails: normalizeAccessEmails(params.accessEmails),\n });\n }\n\n /**\n * Update document (creates new version)\n * Set status to \"published\" to verify in blockchain.\n */\n async update(documentId: string, params: UpdateDocumentParams): Promise<DocumentResponse> {\n return this.client.put<DocumentResponse>(`/api/v1/documents/${documentId}`, params);\n }\n\n /**\n * Update document access rights\n */\n async updateRights(documentId: string, params: UpdateDocumentRightsParams): Promise<DocumentResponse> {\n return this.client.put<DocumentResponse>(`/api/v1/documents/${documentId}/rights`, {\n ...params,\n accessEmails: normalizeAccessEmails(params.accessEmails),\n });\n }\n\n /**\n * Verify document in blockchain\n */\n async verify(params: VerifyDocumentParams): Promise<VerifyDocumentResponse> {\n return this.client.post<VerifyDocumentResponse>('/api/v1/documents/verify', params);\n }\n\n /**\n * Get verification status for a document version\n */\n async getVerificationStatus(versionId: string): Promise<VerifyDocumentResponse> {\n return this.client.get<VerifyDocumentResponse>(`/api/v1/documents/versions/${versionId}/verification`);\n }\n}\n","/**\n * Signatures Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateSignatureRequestParams,\n SignDocumentParams,\n SignatureRequestResponse,\n SignatureRequestStatus,\n PaginationParams,\n GetMyRequestsResponse,\n GetSignaturesResponse,\n} from '../types';\nimport { withNormalizedEmail, withNormalizedSignerEmail } from '../utils/normalize-email';\n\nexport class Signatures {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a signature request\n *\n * When embeddedFlow=true and isKycRequired=true:\n * - Signers complete KYC inside Chaindoc before signing\n * - Backend enforces KYC at signing time\n */\n async createRequest(params: CreateSignatureRequestParams): Promise<SignatureRequestResponse> {\n return this.client.post<SignatureRequestResponse>('/api/v1/signatures/requests', {\n ...params,\n recipients: params.recipients.map(withNormalizedEmail),\n fields: params.fields?.map(withNormalizedSignerEmail),\n deadline: params.deadline.toISOString(),\n });\n }\n\n /**\n * Get signature request status\n */\n async getRequestStatus(requestId: string): Promise<SignatureRequestStatus> {\n return this.client.get<SignatureRequestStatus>(`/api/v1/signatures/requests/${requestId}/status`);\n }\n\n /**\n * Get all signature requests for current user\n */\n async getMyRequests(pagination?: PaginationParams): Promise<GetMyRequestsResponse> {\n const params = new URLSearchParams();\n if (pagination?.pageNumber) params.set('pageNumber', String(pagination.pageNumber));\n if (pagination?.pageSize) params.set('pageSize', String(pagination.pageSize));\n\n const query = params.toString();\n return this.client.get<GetMyRequestsResponse>(`/api/v1/signatures/requests${query ? `?${query}` : ''}`);\n }\n\n /**\n * Sign a document\n * API key owner must be one of the signatories.\n */\n async sign(params: SignDocumentParams): Promise<{ success: boolean; requestId: string; signedAt: string; message: string }> {\n return this.client.post('/api/v1/signatures/sign', params);\n }\n\n /**\n * Get user's signatures (signature requests where user is a signer)\n */\n async getSignatures(pagination?: PaginationParams): Promise<GetSignaturesResponse> {\n const params = new URLSearchParams();\n if (pagination?.pageNumber) params.set('pageNumber', String(pagination.pageNumber));\n if (pagination?.pageSize) params.set('pageSize', String(pagination.pageSize));\n\n const query = params.toString();\n return this.client.get<GetSignaturesResponse>(`/api/v1/signatures${query ? `?${query}` : ''}`);\n }\n}\n","/**\n * Contracts Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateContractParams,\n ContractResponse,\n ContractListResponse,\n ContractStatusResponse,\n ContractActivitiesResponse,\n PaymentSetupParams,\n TerminateContractParams,\n ContractActionResponse,\n ContractSendResponse,\n ContractSendParams,\n ContractListParams,\n PaginationParams,\n} from '../types';\nimport { withNormalizedEmail } from '../utils/normalize-email';\n\nexport class Contracts {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a new contract\n * Creates a contract in DRAFT status with a document and contragent info.\n * Payment terms can be included or added later via addPaymentSetup().\n */\n async create(params: CreateContractParams): Promise<ContractResponse> {\n return this.client.post<ContractResponse>('/api/v1/contracts', {\n ...params,\n contragent: withNormalizedEmail(params.contragent),\n });\n }\n\n /**\n * List contracts\n * Returns paginated list of contracts with optional filters.\n */\n async list(params?: ContractListParams): Promise<ContractListResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n if (params?.status) query.set('status', params.status);\n if (params?.search) query.set('search', params.search);\n\n const qs = query.toString();\n return this.client.get<ContractListResponse>(`/api/v1/contracts${qs ? `?${qs}` : ''}`);\n }\n\n /**\n * Get contract details\n * Returns full contract details including payment terms and signing status.\n */\n async get(contractId: string): Promise<ContractResponse> {\n return this.client.get<ContractResponse>(`/api/v1/contracts/${contractId}`);\n }\n\n /**\n * Get contract lifecycle status\n * Returns lightweight status summary including signing progress and payment overview.\n */\n async getStatus(contractId: string): Promise<ContractStatusResponse> {\n return this.client.get<ContractStatusResponse>(`/api/v1/contracts/${contractId}/status`);\n }\n\n /**\n * Get contract activity log\n * Returns paginated activity log for the contract.\n */\n async getActivities(contractId: string, params?: PaginationParams): Promise<ContractActivitiesResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n\n const qs = query.toString();\n return this.client.get<ContractActivitiesResponse>(\n `/api/v1/contracts/${contractId}/activities${qs ? `?${qs}` : ''}`\n );\n }\n\n /**\n * Add payment terms to a contract\n * Adds payment terms to a DRAFT contract that was created without them.\n */\n async addPaymentSetup(contractId: string, params: PaymentSetupParams): Promise<ContractResponse> {\n return this.client.post<ContractResponse>(`/api/v1/contracts/${contractId}/payment-setup`, params);\n }\n\n /**\n * Send contract for signing\n * Initiates the signing flow for a DRAFT contract.\n */\n async send(contractId: string, params?: ContractSendParams): Promise<ContractSendResponse> {\n return this.client.post<ContractSendResponse>(`/api/v1/contracts/${contractId}/send`, {\n ...params,\n deadline: params?.deadline?.toISOString(),\n });\n }\n\n /**\n * Cancel contract\n * Cancels a DRAFT contract.\n */\n async cancel(contractId: string): Promise<ContractActionResponse> {\n return this.client.post<ContractActionResponse>(`/api/v1/contracts/${contractId}/cancel`, {});\n }\n\n /**\n * Terminate contract\n * Initiates termination for an ACTIVE contract.\n * For ONE_SIDE: terminates immediately.\n * For MUTUAL_APPROVAL: creates termination request pending counterparty approval.\n */\n async terminate(contractId: string, params?: TerminateContractParams): Promise<ContractActionResponse> {\n return this.client.post<ContractActionResponse>(\n `/api/v1/contracts/${contractId}/terminate`,\n params ?? {}\n );\n }\n}\n","/**\n * Templates Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateContractFromTemplateParams,\n CreateDocumentFromTemplateParams,\n CreateTemplateSignatureRequestParams,\n TemplateContractResponse,\n TemplateDocumentResponse,\n TemplateSignatureRequestResponse,\n} from '../types';\nimport { withNormalizedEmail } from '../utils/normalize-email';\n\nexport class Templates {\n constructor(private client: HttpClient) {}\n\n /**\n * Render a published template and create a draft document.\n */\n async createDocument(\n templateId: string,\n params: CreateDocumentFromTemplateParams,\n ): Promise<TemplateDocumentResponse> {\n return this.client.post<TemplateDocumentResponse>(`/api/v1/templates/${templateId}/documents`, params);\n }\n\n /**\n * Render a published template and immediately create a signature request.\n */\n async sendForSigning(\n templateId: string,\n params: CreateTemplateSignatureRequestParams,\n ): Promise<TemplateSignatureRequestResponse> {\n return this.client.post<TemplateSignatureRequestResponse>(\n `/api/v1/templates/${templateId}/signature-requests`,\n {\n ...params,\n slotAssignments: params.slotAssignments.map(withNormalizedEmail),\n },\n );\n }\n\n /**\n * Render a published template and create a contract with an active signing flow.\n */\n async createContract(\n templateId: string,\n params: CreateContractFromTemplateParams,\n ): Promise<TemplateContractResponse> {\n return this.client.post<TemplateContractResponse>(`/api/v1/templates/${templateId}/contracts`, {\n ...params,\n contragent: withNormalizedEmail(params.contragent),\n });\n }\n}\n","/**\n * Invoices Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateInvoiceParams,\n InvoiceActionResponse,\n InvoiceListParams,\n InvoiceListResponse,\n InvoiceResponse,\n MarkInvoicePaidParams,\n SendInvoiceParams,\n} from '../types';\n\nexport class Invoices {\n constructor(private client: HttpClient) {}\n\n /**\n * Create an invoice for a contract.\n */\n async create(contractId: string, params: CreateInvoiceParams): Promise<InvoiceResponse> {\n return this.client.post<InvoiceResponse>(`/api/v1/contracts/${contractId}/invoices`, params);\n }\n\n /**\n * List invoices for a contract.\n */\n async list(contractId: string, params?: InvoiceListParams): Promise<InvoiceListResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n if (params?.status) query.set('status', params.status);\n if (params?.type) query.set('type', params.type);\n if (typeof params?.overdue === 'boolean') query.set('overdue', String(params.overdue));\n if (params?.dueDateFrom) query.set('dueDateFrom', params.dueDateFrom);\n if (params?.dueDateTo) query.set('dueDateTo', params.dueDateTo);\n\n const qs = query.toString();\n return this.client.get<InvoiceListResponse>(\n `/api/v1/contracts/${contractId}/invoices${qs ? `?${qs}` : ''}`,\n );\n }\n\n /**\n * Get a single invoice by UUID.\n */\n async get(contractId: string, invoiceId: string): Promise<InvoiceResponse> {\n return this.client.get<InvoiceResponse>(`/api/v1/contracts/${contractId}/invoices/${invoiceId}`);\n }\n\n /**\n * Send a draft invoice to the contragent.\n */\n async send(\n contractId: string,\n invoiceId: string,\n params?: SendInvoiceParams,\n ): Promise<InvoiceActionResponse> {\n return this.client.post<InvoiceActionResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/send`,\n params ?? {},\n );\n }\n\n /**\n * Charge the default payment method for the invoice.\n */\n async charge(contractId: string, invoiceId: string): Promise<InvoiceActionResponse> {\n return this.client.post<InvoiceActionResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/charge`,\n {},\n );\n }\n\n /**\n * Mark an invoice as paid for offline/external payments.\n */\n async markPaid(\n contractId: string,\n invoiceId: string,\n params?: MarkInvoicePaidParams,\n ): Promise<InvoiceResponse> {\n return this.client.post<InvoiceResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/mark-paid`,\n params ?? {},\n );\n }\n}\n","/**\n * Transactions Module\n */\n\nimport type { HttpClient } from '../client';\nimport type { TransactionListResponse, TransactionResponse } from '../types';\n\nexport class Transactions {\n constructor(private client: HttpClient) {}\n\n /**\n * List transactions for a contract.\n */\n async listByContract(contractId: string): Promise<TransactionListResponse> {\n return this.client.get<TransactionListResponse>(`/api/v1/contracts/${contractId}/transactions`);\n }\n\n /**\n * Get a single transaction by UUID.\n */\n async get(transactionId: string): Promise<TransactionResponse> {\n return this.client.get<TransactionResponse>(`/api/v1/transactions/${transactionId}`);\n }\n}\n","/**\n * Embedded Sessions Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateEmbeddedSessionParams,\n EmbeddedSessionResponse,\n} from '../types';\nimport { normalizeEmail } from '../utils/normalize-email';\n\nexport class Embedded {\n constructor(private client: HttpClient) {}\n\n /**\n * Create an embedded session for document signing\n *\n * - Session is valid for 10 minutes\n * - OTP will be sent to the provided email\n * - Use returned sessionId with @chaindoc_io/embed-sdk on frontend\n *\n * @example\n * ```typescript\n * const session = await chaindoc.embedded.createSession({\n * email: 'signer@example.com',\n * metadata: {\n * documentId: 'doc_xxx',\n * signatureRequestId: 'req_xxx',\n * returnUrl: 'https://yourapp.com/signing-complete',\n * },\n * });\n *\n * // Pass session.sessionId to frontend\n * // Frontend uses: sdk.openSignatureFlow({ sessionId: session.sessionId })\n * ```\n */\n async createSession(params: CreateEmbeddedSessionParams): Promise<EmbeddedSessionResponse> {\n return this.client.post<EmbeddedSessionResponse>('/api/v1/embedded/sessions', {\n ...params,\n email: normalizeEmail(params.email),\n });\n }\n}\n","/**\n * Media Module\n */\n\nimport type { HttpClient } from '../client';\nimport type { MediaUploadResponse } from '../types';\n\nexport class Media {\n constructor(private client: HttpClient) {}\n\n /**\n * Upload media files\n *\n * Supported file types:\n * - Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT\n * - Images: JPG, JPEG, PNG, GIF, WEBP, SVG\n * - Videos: MP4, AVI, MOV, WMV\n *\n * Use returned media object when creating documents.\n *\n * @example\n * ```typescript\n * import { readFile } from 'fs/promises';\n *\n * const buffer = await readFile('./contract.pdf');\n * const file = new Blob([buffer], { type: 'application/pdf' });\n *\n * const { media } = await chaindoc.media.upload([file]);\n *\n * // Use media[0] when creating document\n * await chaindoc.documents.create({\n * name: 'Contract',\n * media: media[0],\n * // ...\n * });\n * ```\n */\n async upload(files: File[] | Blob[]): Promise<MediaUploadResponse> {\n return this.client.uploadFiles<MediaUploadResponse>('/api/v1/media/upload', files);\n }\n}\n","/**\n * Webhook Verification Utilities\n *\n * Helpers for verifying webhook signatures and parsing webhook payloads\n * from the Chaindoc API.\n *\n * @example\n * ```typescript\n * import { Chaindoc } from '@chaindoc_io/server-sdk';\n *\n * // In your webhook handler:\n * const result = Chaindoc.webhooks.verify(rawBody, signature, timestamp, secret);\n *\n * if (result.valid) {\n * console.log('Event:', result.envelope.type);\n * console.log('Data:', result.envelope.data);\n * }\n * ```\n */\n\nimport { createHmac, timingSafeEqual } from \"crypto\";\nimport type { WebhookEnvelope, WebhookVerificationResult } from \"../types\";\n\n/** Maximum age of a webhook delivery before it's considered stale (5 minutes) */\nconst MAX_TIMESTAMP_AGE_MS = 5 * 60 * 1000;\n\nexport class Webhooks {\n /**\n * Verify a webhook signature and parse the envelope.\n *\n * @param rawBody - The raw request body string (NOT parsed JSON)\n * @param signature - Value of the `X-Chaindoc-Signature` header (e.g. \"v1=abc123...\")\n * @param timestamp - Value of the `X-Chaindoc-Timestamp` header (ISO 8601)\n * @param secret - Your webhook secret from the Chaindoc dashboard\n * @returns Verification result with parsed envelope if valid\n */\n static verify(\n rawBody: string,\n signature: string,\n timestamp: string,\n secret: string\n ): WebhookVerificationResult {\n if (!rawBody || !signature || !timestamp || !secret) {\n return { valid: false };\n }\n\n // Check timestamp freshness to prevent replay attacks\n const deliveryTime = new Date(timestamp).getTime();\n if (isNaN(deliveryTime)) {\n return { valid: false };\n }\n\n const age = Math.abs(Date.now() - deliveryTime);\n if (age > MAX_TIMESTAMP_AGE_MS) {\n return { valid: false };\n }\n\n // Extract hex from \"v1=<hex>\" format\n const match = signature.match(/^v1=([a-f0-9]+)$/i);\n if (!match || !match[1]) {\n return { valid: false };\n }\n const receivedHex: string = match[1];\n\n // Compute expected signature: HMAC-SHA256(timestamp.rawBody)\n const signingInput = `${timestamp}.${rawBody}`;\n const expectedHex = createHmac(\"sha256\", secret)\n .update(signingInput)\n .digest(\"hex\");\n\n // Timing-safe comparison\n if (receivedHex.length !== expectedHex.length) {\n return { valid: false };\n }\n\n const a = Buffer.from(receivedHex, \"hex\");\n const b = Buffer.from(expectedHex, \"hex\");\n\n if (a.length !== b.length) {\n return { valid: false };\n }\n\n if (!timingSafeEqual(a, b)) {\n return { valid: false };\n }\n\n // Parse envelope\n try {\n const envelope: WebhookEnvelope = JSON.parse(rawBody);\n return { valid: true, envelope };\n } catch {\n return { valid: false };\n }\n }\n\n /**\n * Parse a webhook body without verifying the signature.\n * Use this only when you trust the transport layer (e.g. internal queue).\n */\n static parse<T = Record<string, unknown>>(\n rawBody: string\n ): WebhookEnvelope<T> {\n return JSON.parse(rawBody);\n }\n}\n","/**\n * Chaindoc Server SDK\n *\n * @example\n * ```typescript\n * import { Chaindoc } from '@chaindoc_io/server-sdk';\n *\n * const chaindoc = new Chaindoc({\n * secretKey: 'sk_your_secret_key',\n * });\n *\n * // Create a document\n * const doc = await chaindoc.documents.create({\n * name: 'Contract',\n * description: 'Service agreement',\n * media: { type: 'document', key: '/path/to/file.pdf' },\n * hashtags: ['#contract'],\n * status: 'published',\n * });\n *\n * // Create signature request\n * const request = await chaindoc.signatures.createRequest({\n * versionId: doc.document.currentVersion.id,\n * recipients: [{ email: 'signer@example.com' }],\n * deadline: new Date('2025-12-31'),\n * embeddedFlow: true,\n * });\n *\n * // Create embedded session for frontend\n * const session = await chaindoc.embedded.createSession({\n * email: 'signer@example.com',\n * metadata: {\n * documentId: doc.documentId,\n * signatureRequestId: request.requestId,\n * },\n * });\n *\n * // Pass session.sessionId to frontend\n * ```\n */\n\nimport { HttpClient } from \"./client\";\nimport { Documents } from \"./modules/documents\";\nimport { Signatures } from \"./modules/signatures\";\nimport { Contracts } from \"./modules/contracts\";\nimport { Templates } from \"./modules/templates\";\nimport { Invoices } from \"./modules/invoices\";\nimport { Transactions } from \"./modules/transactions\";\nimport { Embedded } from \"./modules/embedded\";\nimport { Media } from \"./modules/media\";\nimport { Webhooks } from \"./modules/webhooks\";\nimport type { ChaindocConfig, ApiKeyInfo, HealthCheckResponse } from \"./types\";\n\nexport class Chaindoc {\n private client: HttpClient;\n\n /**\n * Webhook verification utilities (static)\n *\n * @example\n * ```typescript\n * const result = Chaindoc.webhooks.verify(rawBody, signature, timestamp, secret);\n * ```\n */\n public static readonly webhooks = Webhooks;\n\n /**\n * Documents API\n * Create, update, and verify documents\n */\n public readonly documents: Documents;\n\n /**\n * Signatures API\n * Create signature requests and sign documents\n */\n public readonly signatures: Signatures;\n\n /**\n * Contracts API\n * Create, manage, and track contract lifecycle\n */\n public readonly contracts: Contracts;\n\n /**\n * Templates API\n * Use published templates to generate documents, signature requests, and contracts\n */\n public readonly templates: Templates;\n\n /**\n * Invoices API\n * Create, send, charge, and inspect contract invoices\n */\n public readonly invoices: Invoices;\n\n /**\n * Transactions API\n * Inspect payment transactions across contract invoices\n */\n public readonly transactions: Transactions;\n\n /**\n * Embedded Sessions API\n * Create sessions for embedded document signing\n */\n public readonly embedded: Embedded;\n\n /**\n * Media API\n * Upload files for use in documents\n */\n public readonly media: Media;\n\n constructor(config: ChaindocConfig) {\n this.client = new HttpClient(config);\n\n this.documents = new Documents(this.client);\n this.signatures = new Signatures(this.client);\n this.contracts = new Contracts(this.client);\n this.templates = new Templates(this.client);\n this.invoices = new Invoices(this.client);\n this.transactions = new Transactions(this.client);\n this.embedded = new Embedded(this.client);\n this.media = new Media(this.client);\n }\n\n /**\n * Get current API key information\n */\n async getApiKeyInfo(): Promise<ApiKeyInfo> {\n return this.client.get<ApiKeyInfo>(\"/api/v1/me\");\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<HealthCheckResponse> {\n return this.client.get<HealthCheckResponse>(\"/api/v1/health\");\n }\n}\n"],"mappings":"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","names":["index_exports","__export","Chaindoc","ChaindocError","__toCommonJS","ChaindocError","message","statusCode","response","isRetryable","ENVIRONMENT_URLS","DEFAULT_ENVIRONMENT","DEFAULT_TIMEOUT","DEFAULT_MAX_RETRIES","DEFAULT_BASE_DELAY_MS","DEFAULT_MAX_DELAY_MS","HttpClient","config","environment","attempt","exponentialDelay","cappedDelay","jitter","error","e","ms","resolve","endpoint","options","url","maxAttempts","lastError","controller","timeoutId","data","errorMessage","body","files","fieldName","formData","file","normalizeEmail","value","withNormalizedEmail","input","withNormalizedSignerEmail","normalizeAccessEmails","accessEmails","withNormalizedEmail","Documents","client","params","documentId","versionId","Signatures","client","params","withNormalizedEmail","withNormalizedSignerEmail","requestId","pagination","query","Contracts","client","params","withNormalizedEmail","query","qs","contractId","Templates","client","templateId","params","withNormalizedEmail","Invoices","client","contractId","params","query","qs","invoiceId","Transactions","client","contractId","transactionId","Embedded","client","params","normalizeEmail","Media","client","files","import_crypto","MAX_TIMESTAMP_AGE_MS","Webhooks","rawBody","signature","timestamp","secret","deliveryTime","match","receivedHex","signingInput","expectedHex","a","b","Chaindoc","Webhooks","config","HttpClient","Documents","Signatures","Contracts","Templates","Invoices","Transactions","Embedded","Media"]}

@@ -1,2 +0,2 @@

var p=class extends Error{constructor(t,s,r,a=!1){super(t);this.statusCode=s;this.response=r;this.isRetryable=a;this.name="ChaindocError"}},D={production:"https://api.chaindoc.io",staging:"https://api.chaindoc.io",development:"https://api.chaindoc.io"},q="production",$=3e4,A=3,I=1e3,M=1e4,h=class{baseUrl;secretKey;timeout;defaultHeaders;retryConfig;constructor(e){if(!e.secretKey)throw new p("secretKey is required");if(!e.secretKey.startsWith("sk_"))throw new p('secretKey must start with "sk_"');let t=e.environment??q;this.baseUrl=e.baseUrl??D[t],this.secretKey=e.secretKey,this.timeout=e.timeout??$,this.defaultHeaders={"Content-Type":"application/json",Authorization:`Bearer ${this.secretKey}`,...e.headers},this.retryConfig={maxRetries:e.retry?.maxRetries??A,baseDelayMs:e.retry?.baseDelayMs??I,maxDelayMs:e.retry?.maxDelayMs??M}}getRetryDelay(e){let t=this.retryConfig.baseDelayMs*Math.pow(2,e),s=Math.min(t,this.retryConfig.maxDelayMs),r=s*.25*(Math.random()*2-1);return Math.round(s+r)}isRetryableError(e,t){return t&&t>=500||t===429?!0:e instanceof Error?["ECONNRESET","ECONNREFUSED","ETIMEDOUT","ENOTFOUND","EAI_AGAIN"].some(r=>e.message.includes(r))||e.name==="AbortError":!1}sleep(e){return new Promise(t=>setTimeout(t,e))}async request(e,t={}){let s=`${this.baseUrl}${e}`,r=t.noRetry?1:this.retryConfig.maxRetries+1,a;for(let o=0;o<r;o++){let l=new AbortController,d=setTimeout(()=>l.abort(),t.timeout??this.timeout);try{let i=await fetch(s,{method:t.method??"GET",headers:{...this.defaultHeaders,...t.headers},body:t.body?JSON.stringify(t.body):void 0,signal:l.signal});if(clearTimeout(d),i.status===204||i.headers.get("content-length")==="0")return;let c=i.headers.get("content-type")?.includes("application/json")?await i.json().catch(()=>{}):void 0;if(!i.ok){let u=c&&typeof c=="object"&&"message"in c&&typeof c.message=="string"?c.message:`Request failed with status ${i.status}`,g=this.isRetryableError(null,i.status);if(a=new p(u,i.status,c,g),g&&o<r-1){await this.sleep(this.getRetryDelay(o));continue}throw a}return c}catch(i){if(clearTimeout(d),i instanceof p){if(!i.isRetryable||o>=r-1)throw i;a=i,await this.sleep(this.getRetryDelay(o));continue}let n=this.isRetryableError(i);if(i instanceof Error){let c=i.name==="AbortError"?"Request timeout":i.message;if(a=new p(c,void 0,void 0,n),n&&o<r-1){await this.sleep(this.getRetryDelay(o));continue}throw a}throw new p("Unknown error occurred")}}throw a??new p("Request failed after retries")}async get(e,t){return this.request(e,{...t,method:"GET"})}async post(e,t,s){return this.request(e,{...s,method:"POST",body:t})}async put(e,t,s){return this.request(e,{...s,method:"PUT",body:t})}async delete(e,t){return this.request(e,{...t,method:"DELETE"})}async uploadFiles(e,t,s="media"){let r=this.retryConfig.maxRetries+1,a;for(let o=0;o<r;o++){let l=new FormData;t.forEach(n=>{l.append(s,n)});let d=new AbortController,i=setTimeout(()=>d.abort(),this.timeout*2);try{let n=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:{Authorization:`Bearer ${this.secretKey}`},body:l,signal:d.signal});if(clearTimeout(i),n.status===204||n.headers.get("content-length")==="0")return;let u=n.headers.get("content-type")?.includes("application/json")?await n.json().catch(()=>{}):void 0;if(!n.ok){let g=u&&typeof u=="object"&&"message"in u&&typeof u.message=="string"?u.message:`Upload failed with status ${n.status}`,w=this.isRetryableError(null,n.status);if(a=new p(g,n.status,u,w),w&&o<r-1){await this.sleep(this.getRetryDelay(o));continue}throw a}return u}catch(n){if(clearTimeout(i),n instanceof p){if(!n.isRetryable||o>=r-1)throw n;a=n,await this.sleep(this.getRetryDelay(o));continue}let c=this.isRetryableError(n);if(n instanceof Error){let u=n.name==="AbortError"?"Upload timeout":n.message;if(a=new p(u,void 0,void 0,c),c&&o<r-1){await this.sleep(this.getRetryDelay(o));continue}throw a}throw new p("Unknown error occurred")}}throw a??new p("Upload failed after retries")}};var y=class{constructor(e){this.client=e}async create(e){return this.client.post("/api/v1/documents",e)}async update(e,t){return this.client.put(`/api/v1/documents/${e}`,t)}async updateRights(e,t){return this.client.put(`/api/v1/documents/${e}/rights`,t)}async verify(e){return this.client.post("/api/v1/documents/verify",e)}async getVerificationStatus(e){return this.client.get(`/api/v1/documents/versions/${e}/verification`)}};var R=class{constructor(e){this.client=e}async createRequest(e){return this.client.post("/api/v1/signatures/requests",{...e,deadline:e.deadline.toISOString()})}async getRequestStatus(e){return this.client.get(`/api/v1/signatures/requests/${e}/status`)}async getMyRequests(e){let t=new URLSearchParams;e?.pageNumber&&t.set("pageNumber",String(e.pageNumber)),e?.pageSize&&t.set("pageSize",String(e.pageSize));let s=t.toString();return this.client.get(`/api/v1/signatures/requests${s?`?${s}`:""}`)}async sign(e){return this.client.post("/api/v1/signatures/sign",e)}async getSignatures(e){let t=new URLSearchParams;e?.pageNumber&&t.set("pageNumber",String(e.pageNumber)),e?.pageSize&&t.set("pageSize",String(e.pageSize));let s=t.toString();return this.client.get(`/api/v1/signatures${s?`?${s}`:""}`)}};var f=class{constructor(e){this.client=e}async create(e){return this.client.post("/api/v1/contracts",e)}async list(e){let t=new URLSearchParams;e?.page&&t.set("page",String(e.page)),e?.limit&&t.set("limit",String(e.limit)),e?.status&&t.set("status",e.status),e?.search&&t.set("search",e.search);let s=t.toString();return this.client.get(`/api/v1/contracts${s?`?${s}`:""}`)}async get(e){return this.client.get(`/api/v1/contracts/${e}`)}async getStatus(e){return this.client.get(`/api/v1/contracts/${e}/status`)}async getActivities(e,t){let s=new URLSearchParams;t?.page&&s.set("page",String(t.page)),t?.limit&&s.set("limit",String(t.limit));let r=s.toString();return this.client.get(`/api/v1/contracts/${e}/activities${r?`?${r}`:""}`)}async addPaymentSetup(e,t){return this.client.post(`/api/v1/contracts/${e}/payment-setup`,t)}async send(e,t){return this.client.post(`/api/v1/contracts/${e}/send`,{...t,deadline:t?.deadline?.toISOString()})}async cancel(e){return this.client.post(`/api/v1/contracts/${e}/cancel`,{})}async terminate(e,t){return this.client.post(`/api/v1/contracts/${e}/terminate`,t??{})}};var v=class{constructor(e){this.client=e}async createDocument(e,t){return this.client.post(`/api/v1/templates/${e}/documents`,t)}async sendForSigning(e,t){return this.client.post(`/api/v1/templates/${e}/signature-requests`,t)}async createContract(e,t){return this.client.post(`/api/v1/templates/${e}/contracts`,t)}};var P=class{constructor(e){this.client=e}async create(e,t){return this.client.post(`/api/v1/contracts/${e}/invoices`,t)}async list(e,t){let s=new URLSearchParams;t?.page&&s.set("page",String(t.page)),t?.limit&&s.set("limit",String(t.limit)),t?.status&&s.set("status",t.status),t?.type&&s.set("type",t.type),typeof t?.overdue=="boolean"&&s.set("overdue",String(t.overdue)),t?.dueDateFrom&&s.set("dueDateFrom",t.dueDateFrom),t?.dueDateTo&&s.set("dueDateTo",t.dueDateTo);let r=s.toString();return this.client.get(`/api/v1/contracts/${e}/invoices${r?`?${r}`:""}`)}async get(e,t){return this.client.get(`/api/v1/contracts/${e}/invoices/${t}`)}async send(e,t,s){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/send`,s??{})}async charge(e,t){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/charge`,{})}async markPaid(e,t,s){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/mark-paid`,s??{})}};var C=class{constructor(e){this.client=e}async listByContract(e){return this.client.get(`/api/v1/contracts/${e}/transactions`)}async get(e){return this.client.get(`/api/v1/transactions/${e}`)}};var S=class{constructor(e){this.client=e}async createSession(e){return this.client.post("/api/v1/embedded/sessions",e)}};var T=class{constructor(e){this.client=e}async upload(e){return this.client.uploadFiles("/api/v1/media/upload",e)}};import{createHmac as U,timingSafeEqual as x}from"crypto";var k=300*1e3,b=class{static verify(e,t,s,r){if(!e||!t||!s||!r)return{valid:!1};let a=new Date(s).getTime();if(isNaN(a))return{valid:!1};if(Math.abs(Date.now()-a)>k)return{valid:!1};let l=t.match(/^v1=([a-f0-9]+)$/i);if(!l||!l[1])return{valid:!1};let d=l[1],i=`${s}.${e}`,n=U("sha256",r).update(i).digest("hex");if(d.length!==n.length)return{valid:!1};let c=Buffer.from(d,"hex"),u=Buffer.from(n,"hex");if(c.length!==u.length)return{valid:!1};if(!x(c,u))return{valid:!1};try{return{valid:!0,envelope:JSON.parse(e)}}catch{return{valid:!1}}}static parse(e){return JSON.parse(e)}};var E=class{client;static webhooks=b;documents;signatures;contracts;templates;invoices;transactions;embedded;media;constructor(e){this.client=new h(e),this.documents=new y(this.client),this.signatures=new R(this.client),this.contracts=new f(this.client),this.templates=new v(this.client),this.invoices=new P(this.client),this.transactions=new C(this.client),this.embedded=new S(this.client),this.media=new T(this.client)}async getApiKeyInfo(){return this.client.get("/api/v1/me")}async healthCheck(){return this.client.get("/api/v1/health")}};export{E as Chaindoc,p as ChaindocError};
var p=class extends Error{constructor(t,s,r,c=!1){super(t);this.statusCode=s;this.response=r;this.isRetryable=c;this.name="ChaindocError"}},x={production:"https://api.chaindoc.io",staging:"https://api.chaindoc.io",development:"https://api.chaindoc.io"},I="production",M=3e4,U=3,L=1e3,N=1e4,y=class{baseUrl;secretKey;timeout;defaultHeaders;retryConfig;constructor(e){if(!e.secretKey)throw new p("secretKey is required");if(!e.secretKey.startsWith("sk_"))throw new p('secretKey must start with "sk_"');let t=e.environment??I;this.baseUrl=e.baseUrl??x[t],this.secretKey=e.secretKey,this.timeout=e.timeout??M,this.defaultHeaders={"Content-Type":"application/json",Authorization:`Bearer ${this.secretKey}`,...e.headers},this.retryConfig={maxRetries:e.retry?.maxRetries??U,baseDelayMs:e.retry?.baseDelayMs??L,maxDelayMs:e.retry?.maxDelayMs??N}}getRetryDelay(e){let t=this.retryConfig.baseDelayMs*Math.pow(2,e),s=Math.min(t,this.retryConfig.maxDelayMs),r=s*.25*(Math.random()*2-1);return Math.round(s+r)}isRetryableError(e,t){return t&&t>=500||t===429?!0:e instanceof Error?["ECONNRESET","ECONNREFUSED","ETIMEDOUT","ENOTFOUND","EAI_AGAIN"].some(r=>e.message.includes(r))||e.name==="AbortError":!1}sleep(e){return new Promise(t=>setTimeout(t,e))}async request(e,t={}){let s=`${this.baseUrl}${e}`,r=t.noRetry?1:this.retryConfig.maxRetries+1,c;for(let a=0;a<r;a++){let u=new AbortController,g=setTimeout(()=>u.abort(),t.timeout??this.timeout);try{let o=await fetch(s,{method:t.method??"GET",headers:{...this.defaultHeaders,...t.headers},body:t.body?JSON.stringify(t.body):void 0,signal:u.signal});if(clearTimeout(g),o.status===204||o.headers.get("content-length")==="0")return;let m=o.headers.get("content-type")?.includes("application/json")?await o.json().catch(()=>{}):void 0;if(!o.ok){let l=m&&typeof m=="object"&&"message"in m&&typeof m.message=="string"?m.message:`Request failed with status ${o.status}`,h=this.isRetryableError(null,o.status);if(c=new p(l,o.status,m,h),h&&a<r-1){await this.sleep(this.getRetryDelay(a));continue}throw c}return m}catch(o){if(clearTimeout(g),o instanceof p){if(!o.isRetryable||a>=r-1)throw o;c=o,await this.sleep(this.getRetryDelay(a));continue}let i=this.isRetryableError(o);if(o instanceof Error){let m=o.name==="AbortError"?"Request timeout":o.message;if(c=new p(m,void 0,void 0,i),i&&a<r-1){await this.sleep(this.getRetryDelay(a));continue}throw c}throw new p("Unknown error occurred")}}throw c??new p("Request failed after retries")}async get(e,t){return this.request(e,{...t,method:"GET"})}async post(e,t,s){return this.request(e,{...s,method:"POST",body:t})}async put(e,t,s){return this.request(e,{...s,method:"PUT",body:t})}async delete(e,t){return this.request(e,{...t,method:"DELETE"})}async uploadFiles(e,t,s="media"){let r=this.retryConfig.maxRetries+1,c;for(let a=0;a<r;a++){let u=new FormData;t.forEach(i=>{u.append(s,i)});let g=new AbortController,o=setTimeout(()=>g.abort(),this.timeout*2);try{let i=await fetch(`${this.baseUrl}${e}`,{method:"POST",headers:{Authorization:`Bearer ${this.secretKey}`},body:u,signal:g.signal});if(clearTimeout(o),i.status===204||i.headers.get("content-length")==="0")return;let l=i.headers.get("content-type")?.includes("application/json")?await i.json().catch(()=>{}):void 0;if(!i.ok){let h=l&&typeof l=="object"&&"message"in l&&typeof l.message=="string"?l.message:`Upload failed with status ${i.status}`,D=this.isRetryableError(null,i.status);if(c=new p(h,i.status,l,D),D&&a<r-1){await this.sleep(this.getRetryDelay(a));continue}throw c}return l}catch(i){if(clearTimeout(o),i instanceof p){if(!i.isRetryable||a>=r-1)throw i;c=i,await this.sleep(this.getRetryDelay(a));continue}let m=this.isRetryableError(i);if(i instanceof Error){let l=i.name==="AbortError"?"Upload timeout":i.message;if(c=new p(l,void 0,void 0,m),m&&a<r-1){await this.sleep(this.getRetryDelay(a));continue}throw c}throw new p("Unknown error occurred")}}throw c??new p("Upload failed after retries")}};function A(n){return typeof n!="string"?n:n.trim().toLowerCase()}function d(n){return typeof n.email!="string"?{...n}:{...n,email:n.email.trim().toLowerCase()}}function q(n){return typeof n.signerEmail!="string"?{...n}:{...n,signerEmail:n.signerEmail.trim().toLowerCase()}}function $(n){return n?.map(d)}var f=class{constructor(e){this.client=e}async create(e){return this.client.post("/api/v1/documents",{...e,accessEmails:$(e.accessEmails)})}async update(e,t){return this.client.put(`/api/v1/documents/${e}`,t)}async updateRights(e,t){return this.client.put(`/api/v1/documents/${e}/rights`,{...t,accessEmails:$(t.accessEmails)})}async verify(e){return this.client.post("/api/v1/documents/verify",e)}async getVerificationStatus(e){return this.client.get(`/api/v1/documents/versions/${e}/verification`)}};var R=class{constructor(e){this.client=e}async createRequest(e){return this.client.post("/api/v1/signatures/requests",{...e,recipients:e.recipients.map(d),fields:e.fields?.map(q),deadline:e.deadline.toISOString()})}async getRequestStatus(e){return this.client.get(`/api/v1/signatures/requests/${e}/status`)}async getMyRequests(e){let t=new URLSearchParams;e?.pageNumber&&t.set("pageNumber",String(e.pageNumber)),e?.pageSize&&t.set("pageSize",String(e.pageSize));let s=t.toString();return this.client.get(`/api/v1/signatures/requests${s?`?${s}`:""}`)}async sign(e){return this.client.post("/api/v1/signatures/sign",e)}async getSignatures(e){let t=new URLSearchParams;e?.pageNumber&&t.set("pageNumber",String(e.pageNumber)),e?.pageSize&&t.set("pageSize",String(e.pageSize));let s=t.toString();return this.client.get(`/api/v1/signatures${s?`?${s}`:""}`)}};var v=class{constructor(e){this.client=e}async create(e){return this.client.post("/api/v1/contracts",{...e,contragent:d(e.contragent)})}async list(e){let t=new URLSearchParams;e?.page&&t.set("page",String(e.page)),e?.limit&&t.set("limit",String(e.limit)),e?.status&&t.set("status",e.status),e?.search&&t.set("search",e.search);let s=t.toString();return this.client.get(`/api/v1/contracts${s?`?${s}`:""}`)}async get(e){return this.client.get(`/api/v1/contracts/${e}`)}async getStatus(e){return this.client.get(`/api/v1/contracts/${e}/status`)}async getActivities(e,t){let s=new URLSearchParams;t?.page&&s.set("page",String(t.page)),t?.limit&&s.set("limit",String(t.limit));let r=s.toString();return this.client.get(`/api/v1/contracts/${e}/activities${r?`?${r}`:""}`)}async addPaymentSetup(e,t){return this.client.post(`/api/v1/contracts/${e}/payment-setup`,t)}async send(e,t){return this.client.post(`/api/v1/contracts/${e}/send`,{...t,deadline:t?.deadline?.toISOString()})}async cancel(e){return this.client.post(`/api/v1/contracts/${e}/cancel`,{})}async terminate(e,t){return this.client.post(`/api/v1/contracts/${e}/terminate`,t??{})}};var P=class{constructor(e){this.client=e}async createDocument(e,t){return this.client.post(`/api/v1/templates/${e}/documents`,t)}async sendForSigning(e,t){return this.client.post(`/api/v1/templates/${e}/signature-requests`,{...t,slotAssignments:t.slotAssignments.map(d)})}async createContract(e,t){return this.client.post(`/api/v1/templates/${e}/contracts`,{...t,contragent:d(t.contragent)})}};var C=class{constructor(e){this.client=e}async create(e,t){return this.client.post(`/api/v1/contracts/${e}/invoices`,t)}async list(e,t){let s=new URLSearchParams;t?.page&&s.set("page",String(t.page)),t?.limit&&s.set("limit",String(t.limit)),t?.status&&s.set("status",t.status),t?.type&&s.set("type",t.type),typeof t?.overdue=="boolean"&&s.set("overdue",String(t.overdue)),t?.dueDateFrom&&s.set("dueDateFrom",t.dueDateFrom),t?.dueDateTo&&s.set("dueDateTo",t.dueDateTo);let r=s.toString();return this.client.get(`/api/v1/contracts/${e}/invoices${r?`?${r}`:""}`)}async get(e,t){return this.client.get(`/api/v1/contracts/${e}/invoices/${t}`)}async send(e,t,s){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/send`,s??{})}async charge(e,t){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/charge`,{})}async markPaid(e,t,s){return this.client.post(`/api/v1/contracts/${e}/invoices/${t}/mark-paid`,s??{})}};var T=class{constructor(e){this.client=e}async listByContract(e){return this.client.get(`/api/v1/contracts/${e}/transactions`)}async get(e){return this.client.get(`/api/v1/transactions/${e}`)}};var S=class{constructor(e){this.client=e}async createSession(e){return this.client.post("/api/v1/embedded/sessions",{...e,email:A(e.email)})}};var E=class{constructor(e){this.client=e}async upload(e){return this.client.uploadFiles("/api/v1/media/upload",e)}};import{createHmac as k,timingSafeEqual as H}from"crypto";var O=300*1e3,b=class{static verify(e,t,s,r){if(!e||!t||!s||!r)return{valid:!1};let c=new Date(s).getTime();if(isNaN(c))return{valid:!1};if(Math.abs(Date.now()-c)>O)return{valid:!1};let u=t.match(/^v1=([a-f0-9]+)$/i);if(!u||!u[1])return{valid:!1};let g=u[1],o=`${s}.${e}`,i=k("sha256",r).update(o).digest("hex");if(g.length!==i.length)return{valid:!1};let m=Buffer.from(g,"hex"),l=Buffer.from(i,"hex");if(m.length!==l.length)return{valid:!1};if(!H(m,l))return{valid:!1};try{return{valid:!0,envelope:JSON.parse(e)}}catch{return{valid:!1}}}static parse(e){return JSON.parse(e)}};var w=class{client;static webhooks=b;documents;signatures;contracts;templates;invoices;transactions;embedded;media;constructor(e){this.client=new y(e),this.documents=new f(this.client),this.signatures=new R(this.client),this.contracts=new v(this.client),this.templates=new P(this.client),this.invoices=new C(this.client),this.transactions=new T(this.client),this.embedded=new S(this.client),this.media=new E(this.client)}async getApiKeyInfo(){return this.client.get("/api/v1/me")}async healthCheck(){return this.client.get("/api/v1/health")}};export{w as Chaindoc,p as ChaindocError};
//# sourceMappingURL=index.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/client.ts","../src/modules/documents.ts","../src/modules/signatures.ts","../src/modules/contracts.ts","../src/modules/templates.ts","../src/modules/invoices.ts","../src/modules/transactions.ts","../src/modules/embedded.ts","../src/modules/media.ts","../src/modules/webhooks.ts","../src/chaindoc.ts"],"sourcesContent":["/**\n * HTTP Client for Chaindoc API\n * Uses native fetch (Node 18+)\n */\n\nimport type { ChaindocConfig, ChaindocEnvironment, RetryConfig } from \"./types\";\n\nexport class ChaindocError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public response?: unknown,\n public isRetryable: boolean = false\n ) {\n super(message);\n this.name = \"ChaindocError\";\n }\n}\n\nexport interface RequestOptions {\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n body?: unknown;\n headers?: Record<string, string>;\n timeout?: number;\n /** Disable retry for this specific request */\n noRetry?: boolean;\n}\n\nconst ENVIRONMENT_URLS: Record<ChaindocEnvironment, string> = {\n production: \"https://api.chaindoc.io\",\n staging: \"https://api.chaindoc.io\",\n development: \"https://api.chaindoc.io\",\n};\n\nconst DEFAULT_ENVIRONMENT: ChaindocEnvironment = \"production\";\nconst DEFAULT_TIMEOUT = 30000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_BASE_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 10000;\n\nexport class HttpClient {\n private baseUrl: string;\n private secretKey: string;\n private timeout: number;\n private defaultHeaders: Record<string, string>;\n private retryConfig: Required<RetryConfig>;\n\n constructor(config: ChaindocConfig) {\n if (!config.secretKey) {\n throw new ChaindocError(\"secretKey is required\");\n }\n\n if (!config.secretKey.startsWith(\"sk_\")) {\n throw new ChaindocError('secretKey must start with \"sk_\"');\n }\n\n const environment = config.environment ?? DEFAULT_ENVIRONMENT;\n this.baseUrl = config.baseUrl ?? ENVIRONMENT_URLS[environment];\n this.secretKey = config.secretKey;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n this.defaultHeaders = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.secretKey}`,\n ...config.headers,\n };\n this.retryConfig = {\n maxRetries: config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES,\n baseDelayMs: config.retry?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS,\n maxDelayMs: config.retry?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS,\n };\n }\n\n /**\n * Calculate delay with exponential backoff and jitter\n */\n private getRetryDelay(attempt: number): number {\n const exponentialDelay =\n this.retryConfig.baseDelayMs * Math.pow(2, attempt);\n const cappedDelay = Math.min(exponentialDelay, this.retryConfig.maxDelayMs);\n // Add jitter (±25%)\n const jitter = cappedDelay * 0.25 * (Math.random() * 2 - 1);\n return Math.round(cappedDelay + jitter);\n }\n\n /**\n * Check if error is retryable\n */\n private isRetryableError(error: unknown, statusCode?: number): boolean {\n // Retry on 5xx server errors\n if (statusCode && statusCode >= 500) {\n return true;\n }\n // Retry on 429 Too Many Requests\n if (statusCode === 429) {\n return true;\n }\n // Retry on network errors\n if (error instanceof Error) {\n const networkErrors = [\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n \"ETIMEDOUT\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n ];\n return (\n networkErrors.some((e) => error.message.includes(e)) ||\n error.name === \"AbortError\"\n );\n }\n return false;\n }\n\n /**\n * Sleep for specified milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n async request<T>(endpoint: string, options: RequestOptions = {}): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n const maxAttempts = options.noRetry ? 1 : this.retryConfig.maxRetries + 1;\n let lastError: ChaindocError | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n options.timeout ?? this.timeout\n );\n\n try {\n const response = await fetch(url, {\n method: options.method ?? \"GET\",\n headers: {\n ...this.defaultHeaders,\n ...options.headers,\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Handle empty responses (204 No Content, empty body)\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return undefined as T;\n }\n\n // Only parse JSON if content-type indicates JSON\n const contentType = response.headers.get(\"content-type\");\n const data: unknown = contentType?.includes(\"application/json\")\n ? await response.json().catch(() => undefined)\n : undefined;\n\n if (!response.ok) {\n const errorMessage =\n data &&\n typeof data === \"object\" &&\n \"message\" in data &&\n typeof data.message === \"string\"\n ? data.message\n : `Request failed with status ${response.status}`;\n const isRetryable = this.isRetryableError(null, response.status);\n lastError = new ChaindocError(\n errorMessage,\n response.status,\n data,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n return data as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ChaindocError) {\n if (!error.isRetryable || attempt >= maxAttempts - 1) {\n throw error;\n }\n lastError = error;\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n const isRetryable = this.isRetryableError(error);\n if (error instanceof Error) {\n const message =\n error.name === \"AbortError\" ? \"Request timeout\" : error.message;\n lastError = new ChaindocError(\n message,\n undefined,\n undefined,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n throw new ChaindocError(\"Unknown error occurred\");\n }\n }\n\n throw lastError ?? new ChaindocError(\"Request failed after retries\");\n }\n\n async get<T>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"GET\" });\n }\n\n async post<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"POST\", body });\n }\n\n async put<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"PUT\", body });\n }\n\n async delete<T>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"DELETE\" });\n }\n\n /**\n * Upload files using multipart/form-data\n *\n * @remarks Requires Node.js >= 18 (uses native File, Blob, FormData APIs)\n */\n async uploadFiles<T>(\n endpoint: string,\n files: File[] | Blob[],\n fieldName = \"media\"\n ): Promise<T> {\n const maxAttempts = this.retryConfig.maxRetries + 1;\n let lastError: ChaindocError | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const formData = new FormData();\n files.forEach((file) => {\n formData.append(fieldName, file);\n });\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout * 2);\n\n try {\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.secretKey}`,\n },\n body: formData,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return undefined as T;\n }\n\n const contentType = response.headers.get(\"content-type\");\n const data: unknown = contentType?.includes(\"application/json\")\n ? await response.json().catch(() => undefined)\n : undefined;\n\n if (!response.ok) {\n const errorMessage =\n data &&\n typeof data === \"object\" &&\n \"message\" in data &&\n typeof data.message === \"string\"\n ? data.message\n : `Upload failed with status ${response.status}`;\n const isRetryable = this.isRetryableError(null, response.status);\n lastError = new ChaindocError(\n errorMessage,\n response.status,\n data,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n return data as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ChaindocError) {\n if (!error.isRetryable || attempt >= maxAttempts - 1) {\n throw error;\n }\n lastError = error;\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n const isRetryable = this.isRetryableError(error);\n if (error instanceof Error) {\n const message =\n error.name === \"AbortError\" ? \"Upload timeout\" : error.message;\n lastError = new ChaindocError(\n message,\n undefined,\n undefined,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n throw new ChaindocError(\"Unknown error occurred\");\n }\n }\n\n throw lastError ?? new ChaindocError(\"Upload failed after retries\");\n }\n}\n","/**\n * Documents Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateDocumentParams,\n UpdateDocumentParams,\n UpdateDocumentRightsParams,\n DocumentResponse,\n VerifyDocumentParams,\n VerifyDocumentResponse,\n} from '../types';\n\nexport class Documents {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a new document\n * Creates document with first version. Set status to \"published\" to verify in blockchain immediately.\n */\n async create(params: CreateDocumentParams): Promise<DocumentResponse> {\n return this.client.post<DocumentResponse>('/api/v1/documents', params);\n }\n\n /**\n * Update document (creates new version)\n * Set status to \"published\" to verify in blockchain.\n */\n async update(documentId: string, params: UpdateDocumentParams): Promise<DocumentResponse> {\n return this.client.put<DocumentResponse>(`/api/v1/documents/${documentId}`, params);\n }\n\n /**\n * Update document access rights\n */\n async updateRights(documentId: string, params: UpdateDocumentRightsParams): Promise<DocumentResponse> {\n return this.client.put<DocumentResponse>(`/api/v1/documents/${documentId}/rights`, params);\n }\n\n /**\n * Verify document in blockchain\n */\n async verify(params: VerifyDocumentParams): Promise<VerifyDocumentResponse> {\n return this.client.post<VerifyDocumentResponse>('/api/v1/documents/verify', params);\n }\n\n /**\n * Get verification status for a document version\n */\n async getVerificationStatus(versionId: string): Promise<VerifyDocumentResponse> {\n return this.client.get<VerifyDocumentResponse>(`/api/v1/documents/versions/${versionId}/verification`);\n }\n}\n","/**\n * Signatures Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateSignatureRequestParams,\n SignDocumentParams,\n SignatureRequestResponse,\n SignatureRequestStatus,\n PaginationParams,\n GetMyRequestsResponse,\n GetSignaturesResponse,\n} from '../types';\n\nexport class Signatures {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a signature request\n *\n * When embeddedFlow=true and isKycRequired=true:\n * - Signers complete KYC inside Chaindoc before signing\n * - Backend enforces KYC at signing time\n */\n async createRequest(params: CreateSignatureRequestParams): Promise<SignatureRequestResponse> {\n return this.client.post<SignatureRequestResponse>('/api/v1/signatures/requests', {\n ...params,\n deadline: params.deadline.toISOString(),\n });\n }\n\n /**\n * Get signature request status\n */\n async getRequestStatus(requestId: string): Promise<SignatureRequestStatus> {\n return this.client.get<SignatureRequestStatus>(`/api/v1/signatures/requests/${requestId}/status`);\n }\n\n /**\n * Get all signature requests for current user\n */\n async getMyRequests(pagination?: PaginationParams): Promise<GetMyRequestsResponse> {\n const params = new URLSearchParams();\n if (pagination?.pageNumber) params.set('pageNumber', String(pagination.pageNumber));\n if (pagination?.pageSize) params.set('pageSize', String(pagination.pageSize));\n\n const query = params.toString();\n return this.client.get<GetMyRequestsResponse>(`/api/v1/signatures/requests${query ? `?${query}` : ''}`);\n }\n\n /**\n * Sign a document\n * API key owner must be one of the signatories.\n */\n async sign(params: SignDocumentParams): Promise<{ success: boolean; requestId: string; signedAt: string; message: string }> {\n return this.client.post('/api/v1/signatures/sign', params);\n }\n\n /**\n * Get user's signatures (signature requests where user is a signer)\n */\n async getSignatures(pagination?: PaginationParams): Promise<GetSignaturesResponse> {\n const params = new URLSearchParams();\n if (pagination?.pageNumber) params.set('pageNumber', String(pagination.pageNumber));\n if (pagination?.pageSize) params.set('pageSize', String(pagination.pageSize));\n\n const query = params.toString();\n return this.client.get<GetSignaturesResponse>(`/api/v1/signatures${query ? `?${query}` : ''}`);\n }\n}\n","/**\n * Contracts Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateContractParams,\n ContractResponse,\n ContractListResponse,\n ContractStatusResponse,\n ContractActivitiesResponse,\n PaymentSetupParams,\n TerminateContractParams,\n ContractActionResponse,\n ContractSendResponse,\n ContractSendParams,\n ContractListParams,\n PaginationParams,\n} from '../types';\n\nexport class Contracts {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a new contract\n * Creates a contract in DRAFT status with a document and contragent info.\n * Payment terms can be included or added later via addPaymentSetup().\n */\n async create(params: CreateContractParams): Promise<ContractResponse> {\n return this.client.post<ContractResponse>('/api/v1/contracts', params);\n }\n\n /**\n * List contracts\n * Returns paginated list of contracts with optional filters.\n */\n async list(params?: ContractListParams): Promise<ContractListResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n if (params?.status) query.set('status', params.status);\n if (params?.search) query.set('search', params.search);\n\n const qs = query.toString();\n return this.client.get<ContractListResponse>(`/api/v1/contracts${qs ? `?${qs}` : ''}`);\n }\n\n /**\n * Get contract details\n * Returns full contract details including payment terms and signing status.\n */\n async get(contractId: string): Promise<ContractResponse> {\n return this.client.get<ContractResponse>(`/api/v1/contracts/${contractId}`);\n }\n\n /**\n * Get contract lifecycle status\n * Returns lightweight status summary including signing progress and payment overview.\n */\n async getStatus(contractId: string): Promise<ContractStatusResponse> {\n return this.client.get<ContractStatusResponse>(`/api/v1/contracts/${contractId}/status`);\n }\n\n /**\n * Get contract activity log\n * Returns paginated activity log for the contract.\n */\n async getActivities(contractId: string, params?: PaginationParams): Promise<ContractActivitiesResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n\n const qs = query.toString();\n return this.client.get<ContractActivitiesResponse>(\n `/api/v1/contracts/${contractId}/activities${qs ? `?${qs}` : ''}`\n );\n }\n\n /**\n * Add payment terms to a contract\n * Adds payment terms to a DRAFT contract that was created without them.\n */\n async addPaymentSetup(contractId: string, params: PaymentSetupParams): Promise<ContractResponse> {\n return this.client.post<ContractResponse>(`/api/v1/contracts/${contractId}/payment-setup`, params);\n }\n\n /**\n * Send contract for signing\n * Initiates the signing flow for a DRAFT contract.\n */\n async send(contractId: string, params?: ContractSendParams): Promise<ContractSendResponse> {\n return this.client.post<ContractSendResponse>(`/api/v1/contracts/${contractId}/send`, {\n ...params,\n deadline: params?.deadline?.toISOString(),\n });\n }\n\n /**\n * Cancel contract\n * Cancels a DRAFT contract.\n */\n async cancel(contractId: string): Promise<ContractActionResponse> {\n return this.client.post<ContractActionResponse>(`/api/v1/contracts/${contractId}/cancel`, {});\n }\n\n /**\n * Terminate contract\n * Initiates termination for an ACTIVE contract.\n * For ONE_SIDE: terminates immediately.\n * For MUTUAL_APPROVAL: creates termination request pending counterparty approval.\n */\n async terminate(contractId: string, params?: TerminateContractParams): Promise<ContractActionResponse> {\n return this.client.post<ContractActionResponse>(\n `/api/v1/contracts/${contractId}/terminate`,\n params ?? {}\n );\n }\n}\n","/**\n * Templates Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateContractFromTemplateParams,\n CreateDocumentFromTemplateParams,\n CreateTemplateSignatureRequestParams,\n TemplateContractResponse,\n TemplateDocumentResponse,\n TemplateSignatureRequestResponse,\n} from '../types';\n\nexport class Templates {\n constructor(private client: HttpClient) {}\n\n /**\n * Render a published template and create a draft document.\n */\n async createDocument(\n templateId: string,\n params: CreateDocumentFromTemplateParams,\n ): Promise<TemplateDocumentResponse> {\n return this.client.post<TemplateDocumentResponse>(`/api/v1/templates/${templateId}/documents`, params);\n }\n\n /**\n * Render a published template and immediately create a signature request.\n */\n async sendForSigning(\n templateId: string,\n params: CreateTemplateSignatureRequestParams,\n ): Promise<TemplateSignatureRequestResponse> {\n return this.client.post<TemplateSignatureRequestResponse>(\n `/api/v1/templates/${templateId}/signature-requests`,\n params,\n );\n }\n\n /**\n * Render a published template and create a contract with an active signing flow.\n */\n async createContract(\n templateId: string,\n params: CreateContractFromTemplateParams,\n ): Promise<TemplateContractResponse> {\n return this.client.post<TemplateContractResponse>(`/api/v1/templates/${templateId}/contracts`, params);\n }\n}\n","/**\n * Invoices Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateInvoiceParams,\n InvoiceActionResponse,\n InvoiceListParams,\n InvoiceListResponse,\n InvoiceResponse,\n MarkInvoicePaidParams,\n SendInvoiceParams,\n} from '../types';\n\nexport class Invoices {\n constructor(private client: HttpClient) {}\n\n /**\n * Create an invoice for a contract.\n */\n async create(contractId: string, params: CreateInvoiceParams): Promise<InvoiceResponse> {\n return this.client.post<InvoiceResponse>(`/api/v1/contracts/${contractId}/invoices`, params);\n }\n\n /**\n * List invoices for a contract.\n */\n async list(contractId: string, params?: InvoiceListParams): Promise<InvoiceListResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n if (params?.status) query.set('status', params.status);\n if (params?.type) query.set('type', params.type);\n if (typeof params?.overdue === 'boolean') query.set('overdue', String(params.overdue));\n if (params?.dueDateFrom) query.set('dueDateFrom', params.dueDateFrom);\n if (params?.dueDateTo) query.set('dueDateTo', params.dueDateTo);\n\n const qs = query.toString();\n return this.client.get<InvoiceListResponse>(\n `/api/v1/contracts/${contractId}/invoices${qs ? `?${qs}` : ''}`,\n );\n }\n\n /**\n * Get a single invoice by UUID.\n */\n async get(contractId: string, invoiceId: string): Promise<InvoiceResponse> {\n return this.client.get<InvoiceResponse>(`/api/v1/contracts/${contractId}/invoices/${invoiceId}`);\n }\n\n /**\n * Send a draft invoice to the contragent.\n */\n async send(\n contractId: string,\n invoiceId: string,\n params?: SendInvoiceParams,\n ): Promise<InvoiceActionResponse> {\n return this.client.post<InvoiceActionResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/send`,\n params ?? {},\n );\n }\n\n /**\n * Charge the default payment method for the invoice.\n */\n async charge(contractId: string, invoiceId: string): Promise<InvoiceActionResponse> {\n return this.client.post<InvoiceActionResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/charge`,\n {},\n );\n }\n\n /**\n * Mark an invoice as paid for offline/external payments.\n */\n async markPaid(\n contractId: string,\n invoiceId: string,\n params?: MarkInvoicePaidParams,\n ): Promise<InvoiceResponse> {\n return this.client.post<InvoiceResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/mark-paid`,\n params ?? {},\n );\n }\n}\n","/**\n * Transactions Module\n */\n\nimport type { HttpClient } from '../client';\nimport type { TransactionListResponse, TransactionResponse } from '../types';\n\nexport class Transactions {\n constructor(private client: HttpClient) {}\n\n /**\n * List transactions for a contract.\n */\n async listByContract(contractId: string): Promise<TransactionListResponse> {\n return this.client.get<TransactionListResponse>(`/api/v1/contracts/${contractId}/transactions`);\n }\n\n /**\n * Get a single transaction by UUID.\n */\n async get(transactionId: string): Promise<TransactionResponse> {\n return this.client.get<TransactionResponse>(`/api/v1/transactions/${transactionId}`);\n }\n}\n","/**\n * Embedded Sessions Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateEmbeddedSessionParams,\n EmbeddedSessionResponse,\n} from '../types';\n\nexport class Embedded {\n constructor(private client: HttpClient) {}\n\n /**\n * Create an embedded session for document signing\n *\n * - Session is valid for 10 minutes\n * - OTP will be sent to the provided email\n * - Use returned sessionId with @chaindoc_io/embed-sdk on frontend\n *\n * @example\n * ```typescript\n * const session = await chaindoc.embedded.createSession({\n * email: 'signer@example.com',\n * metadata: {\n * documentId: 'doc_xxx',\n * signatureRequestId: 'req_xxx',\n * returnUrl: 'https://yourapp.com/signing-complete',\n * },\n * });\n *\n * // Pass session.sessionId to frontend\n * // Frontend uses: sdk.openSignatureFlow({ sessionId: session.sessionId })\n * ```\n */\n async createSession(params: CreateEmbeddedSessionParams): Promise<EmbeddedSessionResponse> {\n return this.client.post<EmbeddedSessionResponse>('/api/v1/embedded/sessions', params);\n }\n}\n","/**\n * Media Module\n */\n\nimport type { HttpClient } from '../client';\nimport type { MediaUploadResponse } from '../types';\n\nexport class Media {\n constructor(private client: HttpClient) {}\n\n /**\n * Upload media files\n *\n * Supported file types:\n * - Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT\n * - Images: JPG, JPEG, PNG, GIF, WEBP, SVG\n * - Videos: MP4, AVI, MOV, WMV\n *\n * Use returned media object when creating documents.\n *\n * @example\n * ```typescript\n * import { readFile } from 'fs/promises';\n *\n * const buffer = await readFile('./contract.pdf');\n * const file = new Blob([buffer], { type: 'application/pdf' });\n *\n * const { media } = await chaindoc.media.upload([file]);\n *\n * // Use media[0] when creating document\n * await chaindoc.documents.create({\n * name: 'Contract',\n * media: media[0],\n * // ...\n * });\n * ```\n */\n async upload(files: File[] | Blob[]): Promise<MediaUploadResponse> {\n return this.client.uploadFiles<MediaUploadResponse>('/api/v1/media/upload', files);\n }\n}\n","/**\n * Webhook Verification Utilities\n *\n * Helpers for verifying webhook signatures and parsing webhook payloads\n * from the Chaindoc API.\n *\n * @example\n * ```typescript\n * import { Chaindoc } from '@chaindoc_io/server-sdk';\n *\n * // In your webhook handler:\n * const result = Chaindoc.webhooks.verify(rawBody, signature, timestamp, secret);\n *\n * if (result.valid) {\n * console.log('Event:', result.envelope.type);\n * console.log('Data:', result.envelope.data);\n * }\n * ```\n */\n\nimport { createHmac, timingSafeEqual } from \"crypto\";\nimport type { WebhookEnvelope, WebhookVerificationResult } from \"../types\";\n\n/** Maximum age of a webhook delivery before it's considered stale (5 minutes) */\nconst MAX_TIMESTAMP_AGE_MS = 5 * 60 * 1000;\n\nexport class Webhooks {\n /**\n * Verify a webhook signature and parse the envelope.\n *\n * @param rawBody - The raw request body string (NOT parsed JSON)\n * @param signature - Value of the `X-Chaindoc-Signature` header (e.g. \"v1=abc123...\")\n * @param timestamp - Value of the `X-Chaindoc-Timestamp` header (ISO 8601)\n * @param secret - Your webhook secret from the Chaindoc dashboard\n * @returns Verification result with parsed envelope if valid\n */\n static verify(\n rawBody: string,\n signature: string,\n timestamp: string,\n secret: string\n ): WebhookVerificationResult {\n if (!rawBody || !signature || !timestamp || !secret) {\n return { valid: false };\n }\n\n // Check timestamp freshness to prevent replay attacks\n const deliveryTime = new Date(timestamp).getTime();\n if (isNaN(deliveryTime)) {\n return { valid: false };\n }\n\n const age = Math.abs(Date.now() - deliveryTime);\n if (age > MAX_TIMESTAMP_AGE_MS) {\n return { valid: false };\n }\n\n // Extract hex from \"v1=<hex>\" format\n const match = signature.match(/^v1=([a-f0-9]+)$/i);\n if (!match || !match[1]) {\n return { valid: false };\n }\n const receivedHex: string = match[1];\n\n // Compute expected signature: HMAC-SHA256(timestamp.rawBody)\n const signingInput = `${timestamp}.${rawBody}`;\n const expectedHex = createHmac(\"sha256\", secret)\n .update(signingInput)\n .digest(\"hex\");\n\n // Timing-safe comparison\n if (receivedHex.length !== expectedHex.length) {\n return { valid: false };\n }\n\n const a = Buffer.from(receivedHex, \"hex\");\n const b = Buffer.from(expectedHex, \"hex\");\n\n if (a.length !== b.length) {\n return { valid: false };\n }\n\n if (!timingSafeEqual(a, b)) {\n return { valid: false };\n }\n\n // Parse envelope\n try {\n const envelope: WebhookEnvelope = JSON.parse(rawBody);\n return { valid: true, envelope };\n } catch {\n return { valid: false };\n }\n }\n\n /**\n * Parse a webhook body without verifying the signature.\n * Use this only when you trust the transport layer (e.g. internal queue).\n */\n static parse<T = Record<string, unknown>>(\n rawBody: string\n ): WebhookEnvelope<T> {\n return JSON.parse(rawBody);\n }\n}\n","/**\n * Chaindoc Server SDK\n *\n * @example\n * ```typescript\n * import { Chaindoc } from '@chaindoc_io/server-sdk';\n *\n * const chaindoc = new Chaindoc({\n * secretKey: 'sk_your_secret_key',\n * });\n *\n * // Create a document\n * const doc = await chaindoc.documents.create({\n * name: 'Contract',\n * description: 'Service agreement',\n * media: { type: 'document', key: '/path/to/file.pdf' },\n * hashtags: ['#contract'],\n * status: 'published',\n * });\n *\n * // Create signature request\n * const request = await chaindoc.signatures.createRequest({\n * versionId: doc.document.currentVersion.id,\n * recipients: [{ email: 'signer@example.com' }],\n * deadline: new Date('2025-12-31'),\n * embeddedFlow: true,\n * });\n *\n * // Create embedded session for frontend\n * const session = await chaindoc.embedded.createSession({\n * email: 'signer@example.com',\n * metadata: {\n * documentId: doc.documentId,\n * signatureRequestId: request.requestId,\n * },\n * });\n *\n * // Pass session.sessionId to frontend\n * ```\n */\n\nimport { HttpClient } from \"./client\";\nimport { Documents } from \"./modules/documents\";\nimport { Signatures } from \"./modules/signatures\";\nimport { Contracts } from \"./modules/contracts\";\nimport { Templates } from \"./modules/templates\";\nimport { Invoices } from \"./modules/invoices\";\nimport { Transactions } from \"./modules/transactions\";\nimport { Embedded } from \"./modules/embedded\";\nimport { Media } from \"./modules/media\";\nimport { Webhooks } from \"./modules/webhooks\";\nimport type { ChaindocConfig, ApiKeyInfo, HealthCheckResponse } from \"./types\";\n\nexport class Chaindoc {\n private client: HttpClient;\n\n /**\n * Webhook verification utilities (static)\n *\n * @example\n * ```typescript\n * const result = Chaindoc.webhooks.verify(rawBody, signature, timestamp, secret);\n * ```\n */\n public static readonly webhooks = Webhooks;\n\n /**\n * Documents API\n * Create, update, and verify documents\n */\n public readonly documents: Documents;\n\n /**\n * Signatures API\n * Create signature requests and sign documents\n */\n public readonly signatures: Signatures;\n\n /**\n * Contracts API\n * Create, manage, and track contract lifecycle\n */\n public readonly contracts: Contracts;\n\n /**\n * Templates API\n * Use published templates to generate documents, signature requests, and contracts\n */\n public readonly templates: Templates;\n\n /**\n * Invoices API\n * Create, send, charge, and inspect contract invoices\n */\n public readonly invoices: Invoices;\n\n /**\n * Transactions API\n * Inspect payment transactions across contract invoices\n */\n public readonly transactions: Transactions;\n\n /**\n * Embedded Sessions API\n * Create sessions for embedded document signing\n */\n public readonly embedded: Embedded;\n\n /**\n * Media API\n * Upload files for use in documents\n */\n public readonly media: Media;\n\n constructor(config: ChaindocConfig) {\n this.client = new HttpClient(config);\n\n this.documents = new Documents(this.client);\n this.signatures = new Signatures(this.client);\n this.contracts = new Contracts(this.client);\n this.templates = new Templates(this.client);\n this.invoices = new Invoices(this.client);\n this.transactions = new Transactions(this.client);\n this.embedded = new Embedded(this.client);\n this.media = new Media(this.client);\n }\n\n /**\n * Get current API key information\n */\n async getApiKeyInfo(): Promise<ApiKeyInfo> {\n return this.client.get<ApiKeyInfo>(\"/api/v1/me\");\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<HealthCheckResponse> {\n return this.client.get<HealthCheckResponse>(\"/api/v1/health\");\n }\n}\n"],"mappings":"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","names":["ChaindocError","message","statusCode","response","isRetryable","ENVIRONMENT_URLS","DEFAULT_ENVIRONMENT","DEFAULT_TIMEOUT","DEFAULT_MAX_RETRIES","DEFAULT_BASE_DELAY_MS","DEFAULT_MAX_DELAY_MS","HttpClient","config","environment","attempt","exponentialDelay","cappedDelay","jitter","error","e","ms","resolve","endpoint","options","url","maxAttempts","lastError","controller","timeoutId","data","errorMessage","body","files","fieldName","formData","file","Documents","client","params","documentId","versionId","Signatures","client","params","requestId","pagination","query","Contracts","client","params","query","qs","contractId","Templates","client","templateId","params","Invoices","client","contractId","params","query","qs","invoiceId","Transactions","client","contractId","transactionId","Embedded","client","params","Media","client","files","createHmac","timingSafeEqual","MAX_TIMESTAMP_AGE_MS","Webhooks","rawBody","signature","timestamp","secret","deliveryTime","match","receivedHex","signingInput","expectedHex","a","b","Chaindoc","Webhooks","config","HttpClient","Documents","Signatures","Contracts","Templates","Invoices","Transactions","Embedded","Media"]}
{"version":3,"sources":["../src/client.ts","../src/utils/normalize-email.ts","../src/modules/documents.ts","../src/modules/signatures.ts","../src/modules/contracts.ts","../src/modules/templates.ts","../src/modules/invoices.ts","../src/modules/transactions.ts","../src/modules/embedded.ts","../src/modules/media.ts","../src/modules/webhooks.ts","../src/chaindoc.ts"],"sourcesContent":["/**\n * HTTP Client for Chaindoc API\n * Uses native fetch (Node 18+)\n */\n\nimport type { ChaindocConfig, ChaindocEnvironment, RetryConfig } from \"./types\";\n\nexport class ChaindocError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public response?: unknown,\n public isRetryable: boolean = false\n ) {\n super(message);\n this.name = \"ChaindocError\";\n }\n}\n\nexport interface RequestOptions {\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n body?: unknown;\n headers?: Record<string, string>;\n timeout?: number;\n /** Disable retry for this specific request */\n noRetry?: boolean;\n}\n\nconst ENVIRONMENT_URLS: Record<ChaindocEnvironment, string> = {\n production: \"https://api.chaindoc.io\",\n staging: \"https://api.chaindoc.io\",\n development: \"https://api.chaindoc.io\",\n};\n\nconst DEFAULT_ENVIRONMENT: ChaindocEnvironment = \"production\";\nconst DEFAULT_TIMEOUT = 30000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_BASE_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 10000;\n\nexport class HttpClient {\n private baseUrl: string;\n private secretKey: string;\n private timeout: number;\n private defaultHeaders: Record<string, string>;\n private retryConfig: Required<RetryConfig>;\n\n constructor(config: ChaindocConfig) {\n if (!config.secretKey) {\n throw new ChaindocError(\"secretKey is required\");\n }\n\n if (!config.secretKey.startsWith(\"sk_\")) {\n throw new ChaindocError('secretKey must start with \"sk_\"');\n }\n\n const environment = config.environment ?? DEFAULT_ENVIRONMENT;\n this.baseUrl = config.baseUrl ?? ENVIRONMENT_URLS[environment];\n this.secretKey = config.secretKey;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n this.defaultHeaders = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.secretKey}`,\n ...config.headers,\n };\n this.retryConfig = {\n maxRetries: config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES,\n baseDelayMs: config.retry?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS,\n maxDelayMs: config.retry?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS,\n };\n }\n\n /**\n * Calculate delay with exponential backoff and jitter\n */\n private getRetryDelay(attempt: number): number {\n const exponentialDelay =\n this.retryConfig.baseDelayMs * Math.pow(2, attempt);\n const cappedDelay = Math.min(exponentialDelay, this.retryConfig.maxDelayMs);\n // Add jitter (±25%)\n const jitter = cappedDelay * 0.25 * (Math.random() * 2 - 1);\n return Math.round(cappedDelay + jitter);\n }\n\n /**\n * Check if error is retryable\n */\n private isRetryableError(error: unknown, statusCode?: number): boolean {\n // Retry on 5xx server errors\n if (statusCode && statusCode >= 500) {\n return true;\n }\n // Retry on 429 Too Many Requests\n if (statusCode === 429) {\n return true;\n }\n // Retry on network errors\n if (error instanceof Error) {\n const networkErrors = [\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n \"ETIMEDOUT\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n ];\n return (\n networkErrors.some((e) => error.message.includes(e)) ||\n error.name === \"AbortError\"\n );\n }\n return false;\n }\n\n /**\n * Sleep for specified milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n async request<T>(endpoint: string, options: RequestOptions = {}): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n const maxAttempts = options.noRetry ? 1 : this.retryConfig.maxRetries + 1;\n let lastError: ChaindocError | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n options.timeout ?? this.timeout\n );\n\n try {\n const response = await fetch(url, {\n method: options.method ?? \"GET\",\n headers: {\n ...this.defaultHeaders,\n ...options.headers,\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Handle empty responses (204 No Content, empty body)\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return undefined as T;\n }\n\n // Only parse JSON if content-type indicates JSON\n const contentType = response.headers.get(\"content-type\");\n const data: unknown = contentType?.includes(\"application/json\")\n ? await response.json().catch(() => undefined)\n : undefined;\n\n if (!response.ok) {\n const errorMessage =\n data &&\n typeof data === \"object\" &&\n \"message\" in data &&\n typeof data.message === \"string\"\n ? data.message\n : `Request failed with status ${response.status}`;\n const isRetryable = this.isRetryableError(null, response.status);\n lastError = new ChaindocError(\n errorMessage,\n response.status,\n data,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n return data as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ChaindocError) {\n if (!error.isRetryable || attempt >= maxAttempts - 1) {\n throw error;\n }\n lastError = error;\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n const isRetryable = this.isRetryableError(error);\n if (error instanceof Error) {\n const message =\n error.name === \"AbortError\" ? \"Request timeout\" : error.message;\n lastError = new ChaindocError(\n message,\n undefined,\n undefined,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n throw new ChaindocError(\"Unknown error occurred\");\n }\n }\n\n throw lastError ?? new ChaindocError(\"Request failed after retries\");\n }\n\n async get<T>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"GET\" });\n }\n\n async post<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"POST\", body });\n }\n\n async put<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"PUT\", body });\n }\n\n async delete<T>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\" | \"body\">\n ): Promise<T> {\n return this.request<T>(endpoint, { ...options, method: \"DELETE\" });\n }\n\n /**\n * Upload files using multipart/form-data\n *\n * @remarks Requires Node.js >= 18 (uses native File, Blob, FormData APIs)\n */\n async uploadFiles<T>(\n endpoint: string,\n files: File[] | Blob[],\n fieldName = \"media\"\n ): Promise<T> {\n const maxAttempts = this.retryConfig.maxRetries + 1;\n let lastError: ChaindocError | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const formData = new FormData();\n files.forEach((file) => {\n formData.append(fieldName, file);\n });\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout * 2);\n\n try {\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.secretKey}`,\n },\n body: formData,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return undefined as T;\n }\n\n const contentType = response.headers.get(\"content-type\");\n const data: unknown = contentType?.includes(\"application/json\")\n ? await response.json().catch(() => undefined)\n : undefined;\n\n if (!response.ok) {\n const errorMessage =\n data &&\n typeof data === \"object\" &&\n \"message\" in data &&\n typeof data.message === \"string\"\n ? data.message\n : `Upload failed with status ${response.status}`;\n const isRetryable = this.isRetryableError(null, response.status);\n lastError = new ChaindocError(\n errorMessage,\n response.status,\n data,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n return data as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ChaindocError) {\n if (!error.isRetryable || attempt >= maxAttempts - 1) {\n throw error;\n }\n lastError = error;\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n const isRetryable = this.isRetryableError(error);\n if (error instanceof Error) {\n const message =\n error.name === \"AbortError\" ? \"Upload timeout\" : error.message;\n lastError = new ChaindocError(\n message,\n undefined,\n undefined,\n isRetryable\n );\n\n if (isRetryable && attempt < maxAttempts - 1) {\n await this.sleep(this.getRetryDelay(attempt));\n continue;\n }\n\n throw lastError;\n }\n\n throw new ChaindocError(\"Unknown error occurred\");\n }\n }\n\n throw lastError ?? new ChaindocError(\"Upload failed after retries\");\n }\n}\n","/**\n * Email normalization helpers.\n *\n * The Chaindoc backend stores `users.email` lowercased, but historically\n * accepted mixed-case input on signer/contragent/recipient fields. To keep\n * partner integrations from silently dropping auto-link matches, every email\n * payload sent through the SDK is trimmed and lowercased before reaching the\n * wire.\n */\n\nexport function normalizeEmail(value: string): string;\nexport function normalizeEmail(value: string | undefined): string | undefined;\nexport function normalizeEmail(value: string | null): string | null;\nexport function normalizeEmail(value: string | null | undefined): string | null | undefined;\nexport function normalizeEmail(\n value: string | null | undefined,\n): string | null | undefined {\n if (typeof value !== 'string') return value;\n return value.trim().toLowerCase();\n}\n\n/**\n * Returns a shallow copy of `input` with `email` normalized. Leaves the source\n * object untouched so callers can keep using the value they passed in.\n */\nexport function withNormalizedEmail<T extends { email?: string | null | undefined }>(\n input: T,\n): T {\n if (typeof input.email !== 'string') return { ...input };\n return { ...input, email: input.email.trim().toLowerCase() };\n}\n\n/**\n * Returns a shallow copy of `input` with `signerEmail` normalized.\n */\nexport function withNormalizedSignerEmail<\n T extends { signerEmail?: string | null | undefined },\n>(input: T): T {\n if (typeof input.signerEmail !== 'string') return { ...input };\n return { ...input, signerEmail: input.signerEmail.trim().toLowerCase() };\n}\n","/**\n * Documents Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n AccessEmail,\n CreateDocumentParams,\n UpdateDocumentParams,\n UpdateDocumentRightsParams,\n DocumentResponse,\n VerifyDocumentParams,\n VerifyDocumentResponse,\n} from '../types';\nimport { withNormalizedEmail } from '../utils/normalize-email';\n\nfunction normalizeAccessEmails(accessEmails: AccessEmail[] | undefined): AccessEmail[] | undefined {\n return accessEmails?.map(withNormalizedEmail);\n}\n\nexport class Documents {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a new document\n * Creates document with first version. Set status to \"published\" to verify in blockchain immediately.\n */\n async create(params: CreateDocumentParams): Promise<DocumentResponse> {\n return this.client.post<DocumentResponse>('/api/v1/documents', {\n ...params,\n accessEmails: normalizeAccessEmails(params.accessEmails),\n });\n }\n\n /**\n * Update document (creates new version)\n * Set status to \"published\" to verify in blockchain.\n */\n async update(documentId: string, params: UpdateDocumentParams): Promise<DocumentResponse> {\n return this.client.put<DocumentResponse>(`/api/v1/documents/${documentId}`, params);\n }\n\n /**\n * Update document access rights\n */\n async updateRights(documentId: string, params: UpdateDocumentRightsParams): Promise<DocumentResponse> {\n return this.client.put<DocumentResponse>(`/api/v1/documents/${documentId}/rights`, {\n ...params,\n accessEmails: normalizeAccessEmails(params.accessEmails),\n });\n }\n\n /**\n * Verify document in blockchain\n */\n async verify(params: VerifyDocumentParams): Promise<VerifyDocumentResponse> {\n return this.client.post<VerifyDocumentResponse>('/api/v1/documents/verify', params);\n }\n\n /**\n * Get verification status for a document version\n */\n async getVerificationStatus(versionId: string): Promise<VerifyDocumentResponse> {\n return this.client.get<VerifyDocumentResponse>(`/api/v1/documents/versions/${versionId}/verification`);\n }\n}\n","/**\n * Signatures Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateSignatureRequestParams,\n SignDocumentParams,\n SignatureRequestResponse,\n SignatureRequestStatus,\n PaginationParams,\n GetMyRequestsResponse,\n GetSignaturesResponse,\n} from '../types';\nimport { withNormalizedEmail, withNormalizedSignerEmail } from '../utils/normalize-email';\n\nexport class Signatures {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a signature request\n *\n * When embeddedFlow=true and isKycRequired=true:\n * - Signers complete KYC inside Chaindoc before signing\n * - Backend enforces KYC at signing time\n */\n async createRequest(params: CreateSignatureRequestParams): Promise<SignatureRequestResponse> {\n return this.client.post<SignatureRequestResponse>('/api/v1/signatures/requests', {\n ...params,\n recipients: params.recipients.map(withNormalizedEmail),\n fields: params.fields?.map(withNormalizedSignerEmail),\n deadline: params.deadline.toISOString(),\n });\n }\n\n /**\n * Get signature request status\n */\n async getRequestStatus(requestId: string): Promise<SignatureRequestStatus> {\n return this.client.get<SignatureRequestStatus>(`/api/v1/signatures/requests/${requestId}/status`);\n }\n\n /**\n * Get all signature requests for current user\n */\n async getMyRequests(pagination?: PaginationParams): Promise<GetMyRequestsResponse> {\n const params = new URLSearchParams();\n if (pagination?.pageNumber) params.set('pageNumber', String(pagination.pageNumber));\n if (pagination?.pageSize) params.set('pageSize', String(pagination.pageSize));\n\n const query = params.toString();\n return this.client.get<GetMyRequestsResponse>(`/api/v1/signatures/requests${query ? `?${query}` : ''}`);\n }\n\n /**\n * Sign a document\n * API key owner must be one of the signatories.\n */\n async sign(params: SignDocumentParams): Promise<{ success: boolean; requestId: string; signedAt: string; message: string }> {\n return this.client.post('/api/v1/signatures/sign', params);\n }\n\n /**\n * Get user's signatures (signature requests where user is a signer)\n */\n async getSignatures(pagination?: PaginationParams): Promise<GetSignaturesResponse> {\n const params = new URLSearchParams();\n if (pagination?.pageNumber) params.set('pageNumber', String(pagination.pageNumber));\n if (pagination?.pageSize) params.set('pageSize', String(pagination.pageSize));\n\n const query = params.toString();\n return this.client.get<GetSignaturesResponse>(`/api/v1/signatures${query ? `?${query}` : ''}`);\n }\n}\n","/**\n * Contracts Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateContractParams,\n ContractResponse,\n ContractListResponse,\n ContractStatusResponse,\n ContractActivitiesResponse,\n PaymentSetupParams,\n TerminateContractParams,\n ContractActionResponse,\n ContractSendResponse,\n ContractSendParams,\n ContractListParams,\n PaginationParams,\n} from '../types';\nimport { withNormalizedEmail } from '../utils/normalize-email';\n\nexport class Contracts {\n constructor(private client: HttpClient) {}\n\n /**\n * Create a new contract\n * Creates a contract in DRAFT status with a document and contragent info.\n * Payment terms can be included or added later via addPaymentSetup().\n */\n async create(params: CreateContractParams): Promise<ContractResponse> {\n return this.client.post<ContractResponse>('/api/v1/contracts', {\n ...params,\n contragent: withNormalizedEmail(params.contragent),\n });\n }\n\n /**\n * List contracts\n * Returns paginated list of contracts with optional filters.\n */\n async list(params?: ContractListParams): Promise<ContractListResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n if (params?.status) query.set('status', params.status);\n if (params?.search) query.set('search', params.search);\n\n const qs = query.toString();\n return this.client.get<ContractListResponse>(`/api/v1/contracts${qs ? `?${qs}` : ''}`);\n }\n\n /**\n * Get contract details\n * Returns full contract details including payment terms and signing status.\n */\n async get(contractId: string): Promise<ContractResponse> {\n return this.client.get<ContractResponse>(`/api/v1/contracts/${contractId}`);\n }\n\n /**\n * Get contract lifecycle status\n * Returns lightweight status summary including signing progress and payment overview.\n */\n async getStatus(contractId: string): Promise<ContractStatusResponse> {\n return this.client.get<ContractStatusResponse>(`/api/v1/contracts/${contractId}/status`);\n }\n\n /**\n * Get contract activity log\n * Returns paginated activity log for the contract.\n */\n async getActivities(contractId: string, params?: PaginationParams): Promise<ContractActivitiesResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n\n const qs = query.toString();\n return this.client.get<ContractActivitiesResponse>(\n `/api/v1/contracts/${contractId}/activities${qs ? `?${qs}` : ''}`\n );\n }\n\n /**\n * Add payment terms to a contract\n * Adds payment terms to a DRAFT contract that was created without them.\n */\n async addPaymentSetup(contractId: string, params: PaymentSetupParams): Promise<ContractResponse> {\n return this.client.post<ContractResponse>(`/api/v1/contracts/${contractId}/payment-setup`, params);\n }\n\n /**\n * Send contract for signing\n * Initiates the signing flow for a DRAFT contract.\n */\n async send(contractId: string, params?: ContractSendParams): Promise<ContractSendResponse> {\n return this.client.post<ContractSendResponse>(`/api/v1/contracts/${contractId}/send`, {\n ...params,\n deadline: params?.deadline?.toISOString(),\n });\n }\n\n /**\n * Cancel contract\n * Cancels a DRAFT contract.\n */\n async cancel(contractId: string): Promise<ContractActionResponse> {\n return this.client.post<ContractActionResponse>(`/api/v1/contracts/${contractId}/cancel`, {});\n }\n\n /**\n * Terminate contract\n * Initiates termination for an ACTIVE contract.\n * For ONE_SIDE: terminates immediately.\n * For MUTUAL_APPROVAL: creates termination request pending counterparty approval.\n */\n async terminate(contractId: string, params?: TerminateContractParams): Promise<ContractActionResponse> {\n return this.client.post<ContractActionResponse>(\n `/api/v1/contracts/${contractId}/terminate`,\n params ?? {}\n );\n }\n}\n","/**\n * Templates Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateContractFromTemplateParams,\n CreateDocumentFromTemplateParams,\n CreateTemplateSignatureRequestParams,\n TemplateContractResponse,\n TemplateDocumentResponse,\n TemplateSignatureRequestResponse,\n} from '../types';\nimport { withNormalizedEmail } from '../utils/normalize-email';\n\nexport class Templates {\n constructor(private client: HttpClient) {}\n\n /**\n * Render a published template and create a draft document.\n */\n async createDocument(\n templateId: string,\n params: CreateDocumentFromTemplateParams,\n ): Promise<TemplateDocumentResponse> {\n return this.client.post<TemplateDocumentResponse>(`/api/v1/templates/${templateId}/documents`, params);\n }\n\n /**\n * Render a published template and immediately create a signature request.\n */\n async sendForSigning(\n templateId: string,\n params: CreateTemplateSignatureRequestParams,\n ): Promise<TemplateSignatureRequestResponse> {\n return this.client.post<TemplateSignatureRequestResponse>(\n `/api/v1/templates/${templateId}/signature-requests`,\n {\n ...params,\n slotAssignments: params.slotAssignments.map(withNormalizedEmail),\n },\n );\n }\n\n /**\n * Render a published template and create a contract with an active signing flow.\n */\n async createContract(\n templateId: string,\n params: CreateContractFromTemplateParams,\n ): Promise<TemplateContractResponse> {\n return this.client.post<TemplateContractResponse>(`/api/v1/templates/${templateId}/contracts`, {\n ...params,\n contragent: withNormalizedEmail(params.contragent),\n });\n }\n}\n","/**\n * Invoices Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateInvoiceParams,\n InvoiceActionResponse,\n InvoiceListParams,\n InvoiceListResponse,\n InvoiceResponse,\n MarkInvoicePaidParams,\n SendInvoiceParams,\n} from '../types';\n\nexport class Invoices {\n constructor(private client: HttpClient) {}\n\n /**\n * Create an invoice for a contract.\n */\n async create(contractId: string, params: CreateInvoiceParams): Promise<InvoiceResponse> {\n return this.client.post<InvoiceResponse>(`/api/v1/contracts/${contractId}/invoices`, params);\n }\n\n /**\n * List invoices for a contract.\n */\n async list(contractId: string, params?: InvoiceListParams): Promise<InvoiceListResponse> {\n const query = new URLSearchParams();\n if (params?.page) query.set('page', String(params.page));\n if (params?.limit) query.set('limit', String(params.limit));\n if (params?.status) query.set('status', params.status);\n if (params?.type) query.set('type', params.type);\n if (typeof params?.overdue === 'boolean') query.set('overdue', String(params.overdue));\n if (params?.dueDateFrom) query.set('dueDateFrom', params.dueDateFrom);\n if (params?.dueDateTo) query.set('dueDateTo', params.dueDateTo);\n\n const qs = query.toString();\n return this.client.get<InvoiceListResponse>(\n `/api/v1/contracts/${contractId}/invoices${qs ? `?${qs}` : ''}`,\n );\n }\n\n /**\n * Get a single invoice by UUID.\n */\n async get(contractId: string, invoiceId: string): Promise<InvoiceResponse> {\n return this.client.get<InvoiceResponse>(`/api/v1/contracts/${contractId}/invoices/${invoiceId}`);\n }\n\n /**\n * Send a draft invoice to the contragent.\n */\n async send(\n contractId: string,\n invoiceId: string,\n params?: SendInvoiceParams,\n ): Promise<InvoiceActionResponse> {\n return this.client.post<InvoiceActionResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/send`,\n params ?? {},\n );\n }\n\n /**\n * Charge the default payment method for the invoice.\n */\n async charge(contractId: string, invoiceId: string): Promise<InvoiceActionResponse> {\n return this.client.post<InvoiceActionResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/charge`,\n {},\n );\n }\n\n /**\n * Mark an invoice as paid for offline/external payments.\n */\n async markPaid(\n contractId: string,\n invoiceId: string,\n params?: MarkInvoicePaidParams,\n ): Promise<InvoiceResponse> {\n return this.client.post<InvoiceResponse>(\n `/api/v1/contracts/${contractId}/invoices/${invoiceId}/mark-paid`,\n params ?? {},\n );\n }\n}\n","/**\n * Transactions Module\n */\n\nimport type { HttpClient } from '../client';\nimport type { TransactionListResponse, TransactionResponse } from '../types';\n\nexport class Transactions {\n constructor(private client: HttpClient) {}\n\n /**\n * List transactions for a contract.\n */\n async listByContract(contractId: string): Promise<TransactionListResponse> {\n return this.client.get<TransactionListResponse>(`/api/v1/contracts/${contractId}/transactions`);\n }\n\n /**\n * Get a single transaction by UUID.\n */\n async get(transactionId: string): Promise<TransactionResponse> {\n return this.client.get<TransactionResponse>(`/api/v1/transactions/${transactionId}`);\n }\n}\n","/**\n * Embedded Sessions Module\n */\n\nimport type { HttpClient } from '../client';\nimport type {\n CreateEmbeddedSessionParams,\n EmbeddedSessionResponse,\n} from '../types';\nimport { normalizeEmail } from '../utils/normalize-email';\n\nexport class Embedded {\n constructor(private client: HttpClient) {}\n\n /**\n * Create an embedded session for document signing\n *\n * - Session is valid for 10 minutes\n * - OTP will be sent to the provided email\n * - Use returned sessionId with @chaindoc_io/embed-sdk on frontend\n *\n * @example\n * ```typescript\n * const session = await chaindoc.embedded.createSession({\n * email: 'signer@example.com',\n * metadata: {\n * documentId: 'doc_xxx',\n * signatureRequestId: 'req_xxx',\n * returnUrl: 'https://yourapp.com/signing-complete',\n * },\n * });\n *\n * // Pass session.sessionId to frontend\n * // Frontend uses: sdk.openSignatureFlow({ sessionId: session.sessionId })\n * ```\n */\n async createSession(params: CreateEmbeddedSessionParams): Promise<EmbeddedSessionResponse> {\n return this.client.post<EmbeddedSessionResponse>('/api/v1/embedded/sessions', {\n ...params,\n email: normalizeEmail(params.email),\n });\n }\n}\n","/**\n * Media Module\n */\n\nimport type { HttpClient } from '../client';\nimport type { MediaUploadResponse } from '../types';\n\nexport class Media {\n constructor(private client: HttpClient) {}\n\n /**\n * Upload media files\n *\n * Supported file types:\n * - Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT\n * - Images: JPG, JPEG, PNG, GIF, WEBP, SVG\n * - Videos: MP4, AVI, MOV, WMV\n *\n * Use returned media object when creating documents.\n *\n * @example\n * ```typescript\n * import { readFile } from 'fs/promises';\n *\n * const buffer = await readFile('./contract.pdf');\n * const file = new Blob([buffer], { type: 'application/pdf' });\n *\n * const { media } = await chaindoc.media.upload([file]);\n *\n * // Use media[0] when creating document\n * await chaindoc.documents.create({\n * name: 'Contract',\n * media: media[0],\n * // ...\n * });\n * ```\n */\n async upload(files: File[] | Blob[]): Promise<MediaUploadResponse> {\n return this.client.uploadFiles<MediaUploadResponse>('/api/v1/media/upload', files);\n }\n}\n","/**\n * Webhook Verification Utilities\n *\n * Helpers for verifying webhook signatures and parsing webhook payloads\n * from the Chaindoc API.\n *\n * @example\n * ```typescript\n * import { Chaindoc } from '@chaindoc_io/server-sdk';\n *\n * // In your webhook handler:\n * const result = Chaindoc.webhooks.verify(rawBody, signature, timestamp, secret);\n *\n * if (result.valid) {\n * console.log('Event:', result.envelope.type);\n * console.log('Data:', result.envelope.data);\n * }\n * ```\n */\n\nimport { createHmac, timingSafeEqual } from \"crypto\";\nimport type { WebhookEnvelope, WebhookVerificationResult } from \"../types\";\n\n/** Maximum age of a webhook delivery before it's considered stale (5 minutes) */\nconst MAX_TIMESTAMP_AGE_MS = 5 * 60 * 1000;\n\nexport class Webhooks {\n /**\n * Verify a webhook signature and parse the envelope.\n *\n * @param rawBody - The raw request body string (NOT parsed JSON)\n * @param signature - Value of the `X-Chaindoc-Signature` header (e.g. \"v1=abc123...\")\n * @param timestamp - Value of the `X-Chaindoc-Timestamp` header (ISO 8601)\n * @param secret - Your webhook secret from the Chaindoc dashboard\n * @returns Verification result with parsed envelope if valid\n */\n static verify(\n rawBody: string,\n signature: string,\n timestamp: string,\n secret: string\n ): WebhookVerificationResult {\n if (!rawBody || !signature || !timestamp || !secret) {\n return { valid: false };\n }\n\n // Check timestamp freshness to prevent replay attacks\n const deliveryTime = new Date(timestamp).getTime();\n if (isNaN(deliveryTime)) {\n return { valid: false };\n }\n\n const age = Math.abs(Date.now() - deliveryTime);\n if (age > MAX_TIMESTAMP_AGE_MS) {\n return { valid: false };\n }\n\n // Extract hex from \"v1=<hex>\" format\n const match = signature.match(/^v1=([a-f0-9]+)$/i);\n if (!match || !match[1]) {\n return { valid: false };\n }\n const receivedHex: string = match[1];\n\n // Compute expected signature: HMAC-SHA256(timestamp.rawBody)\n const signingInput = `${timestamp}.${rawBody}`;\n const expectedHex = createHmac(\"sha256\", secret)\n .update(signingInput)\n .digest(\"hex\");\n\n // Timing-safe comparison\n if (receivedHex.length !== expectedHex.length) {\n return { valid: false };\n }\n\n const a = Buffer.from(receivedHex, \"hex\");\n const b = Buffer.from(expectedHex, \"hex\");\n\n if (a.length !== b.length) {\n return { valid: false };\n }\n\n if (!timingSafeEqual(a, b)) {\n return { valid: false };\n }\n\n // Parse envelope\n try {\n const envelope: WebhookEnvelope = JSON.parse(rawBody);\n return { valid: true, envelope };\n } catch {\n return { valid: false };\n }\n }\n\n /**\n * Parse a webhook body without verifying the signature.\n * Use this only when you trust the transport layer (e.g. internal queue).\n */\n static parse<T = Record<string, unknown>>(\n rawBody: string\n ): WebhookEnvelope<T> {\n return JSON.parse(rawBody);\n }\n}\n","/**\n * Chaindoc Server SDK\n *\n * @example\n * ```typescript\n * import { Chaindoc } from '@chaindoc_io/server-sdk';\n *\n * const chaindoc = new Chaindoc({\n * secretKey: 'sk_your_secret_key',\n * });\n *\n * // Create a document\n * const doc = await chaindoc.documents.create({\n * name: 'Contract',\n * description: 'Service agreement',\n * media: { type: 'document', key: '/path/to/file.pdf' },\n * hashtags: ['#contract'],\n * status: 'published',\n * });\n *\n * // Create signature request\n * const request = await chaindoc.signatures.createRequest({\n * versionId: doc.document.currentVersion.id,\n * recipients: [{ email: 'signer@example.com' }],\n * deadline: new Date('2025-12-31'),\n * embeddedFlow: true,\n * });\n *\n * // Create embedded session for frontend\n * const session = await chaindoc.embedded.createSession({\n * email: 'signer@example.com',\n * metadata: {\n * documentId: doc.documentId,\n * signatureRequestId: request.requestId,\n * },\n * });\n *\n * // Pass session.sessionId to frontend\n * ```\n */\n\nimport { HttpClient } from \"./client\";\nimport { Documents } from \"./modules/documents\";\nimport { Signatures } from \"./modules/signatures\";\nimport { Contracts } from \"./modules/contracts\";\nimport { Templates } from \"./modules/templates\";\nimport { Invoices } from \"./modules/invoices\";\nimport { Transactions } from \"./modules/transactions\";\nimport { Embedded } from \"./modules/embedded\";\nimport { Media } from \"./modules/media\";\nimport { Webhooks } from \"./modules/webhooks\";\nimport type { ChaindocConfig, ApiKeyInfo, HealthCheckResponse } from \"./types\";\n\nexport class Chaindoc {\n private client: HttpClient;\n\n /**\n * Webhook verification utilities (static)\n *\n * @example\n * ```typescript\n * const result = Chaindoc.webhooks.verify(rawBody, signature, timestamp, secret);\n * ```\n */\n public static readonly webhooks = Webhooks;\n\n /**\n * Documents API\n * Create, update, and verify documents\n */\n public readonly documents: Documents;\n\n /**\n * Signatures API\n * Create signature requests and sign documents\n */\n public readonly signatures: Signatures;\n\n /**\n * Contracts API\n * Create, manage, and track contract lifecycle\n */\n public readonly contracts: Contracts;\n\n /**\n * Templates API\n * Use published templates to generate documents, signature requests, and contracts\n */\n public readonly templates: Templates;\n\n /**\n * Invoices API\n * Create, send, charge, and inspect contract invoices\n */\n public readonly invoices: Invoices;\n\n /**\n * Transactions API\n * Inspect payment transactions across contract invoices\n */\n public readonly transactions: Transactions;\n\n /**\n * Embedded Sessions API\n * Create sessions for embedded document signing\n */\n public readonly embedded: Embedded;\n\n /**\n * Media API\n * Upload files for use in documents\n */\n public readonly media: Media;\n\n constructor(config: ChaindocConfig) {\n this.client = new HttpClient(config);\n\n this.documents = new Documents(this.client);\n this.signatures = new Signatures(this.client);\n this.contracts = new Contracts(this.client);\n this.templates = new Templates(this.client);\n this.invoices = new Invoices(this.client);\n this.transactions = new Transactions(this.client);\n this.embedded = new Embedded(this.client);\n this.media = new Media(this.client);\n }\n\n /**\n * Get current API key information\n */\n async getApiKeyInfo(): Promise<ApiKeyInfo> {\n return this.client.get<ApiKeyInfo>(\"/api/v1/me\");\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<HealthCheckResponse> {\n return this.client.get<HealthCheckResponse>(\"/api/v1/health\");\n }\n}\n"],"mappings":"AAOO,IAAMA,EAAN,cAA4B,KAAM,CACvC,YACEC,EACOC,EACAC,EACAC,EAAuB,GAC9B,CACA,MAAMH,CAAO,EAJN,gBAAAC,EACA,cAAAC,EACA,iBAAAC,EAGP,KAAK,KAAO,eACd,CACF,EAWMC,EAAwD,CAC5D,WAAY,0BACZ,QAAS,0BACT,YAAa,yBACf,EAEMC,EAA2C,aAC3CC,EAAkB,IAClBC,EAAsB,EACtBC,EAAwB,IACxBC,EAAuB,IAEhBC,EAAN,KAAiB,CACd,QACA,UACA,QACA,eACA,YAER,YAAYC,EAAwB,CAClC,GAAI,CAACA,EAAO,UACV,MAAM,IAAIZ,EAAc,uBAAuB,EAGjD,GAAI,CAACY,EAAO,UAAU,WAAW,KAAK,EACpC,MAAM,IAAIZ,EAAc,iCAAiC,EAG3D,IAAMa,EAAcD,EAAO,aAAeN,EAC1C,KAAK,QAAUM,EAAO,SAAWP,EAAiBQ,CAAW,EAC7D,KAAK,UAAYD,EAAO,UACxB,KAAK,QAAUA,EAAO,SAAWL,EACjC,KAAK,eAAiB,CACpB,eAAgB,mBAChB,cAAe,UAAU,KAAK,SAAS,GACvC,GAAGK,EAAO,OACZ,EACA,KAAK,YAAc,CACjB,WAAYA,EAAO,OAAO,YAAcJ,EACxC,YAAaI,EAAO,OAAO,aAAeH,EAC1C,WAAYG,EAAO,OAAO,YAAcF,CAC1C,CACF,CAKQ,cAAcI,EAAyB,CAC7C,IAAMC,EACJ,KAAK,YAAY,YAAc,KAAK,IAAI,EAAGD,CAAO,EAC9CE,EAAc,KAAK,IAAID,EAAkB,KAAK,YAAY,UAAU,EAEpEE,EAASD,EAAc,KAAQ,KAAK,OAAO,EAAI,EAAI,GACzD,OAAO,KAAK,MAAMA,EAAcC,CAAM,CACxC,CAKQ,iBAAiBC,EAAgBhB,EAA8B,CAMrE,OAJIA,GAAcA,GAAc,KAI5BA,IAAe,IACV,GAGLgB,aAAiB,MACG,CACpB,aACA,eACA,YACA,YACA,WACF,EAEgB,KAAMC,GAAMD,EAAM,QAAQ,SAASC,CAAC,CAAC,GACnDD,EAAM,OAAS,aAGZ,EACT,CAKQ,MAAME,EAA2B,CACvC,OAAO,IAAI,QAASC,GAAY,WAAWA,EAASD,CAAE,CAAC,CACzD,CAEA,MAAM,QAAWE,EAAkBC,EAA0B,CAAC,EAAe,CAC3E,IAAMC,EAAM,GAAG,KAAK,OAAO,GAAGF,CAAQ,GAChCG,EAAcF,EAAQ,QAAU,EAAI,KAAK,YAAY,WAAa,EACpEG,EAEJ,QAASZ,EAAU,EAAGA,EAAUW,EAAaX,IAAW,CACtD,IAAMa,EAAa,IAAI,gBACjBC,EAAY,WAChB,IAAMD,EAAW,MAAM,EACvBJ,EAAQ,SAAW,KAAK,OAC1B,EAEA,GAAI,CACF,IAAMpB,EAAW,MAAM,MAAMqB,EAAK,CAChC,OAAQD,EAAQ,QAAU,MAC1B,QAAS,CACP,GAAG,KAAK,eACR,GAAGA,EAAQ,OACb,EACA,KAAMA,EAAQ,KAAO,KAAK,UAAUA,EAAQ,IAAI,EAAI,OACpD,OAAQI,EAAW,MACrB,CAAC,EAKD,GAHA,aAAaC,CAAS,EAIpBzB,EAAS,SAAW,KACpBA,EAAS,QAAQ,IAAI,gBAAgB,IAAM,IAE3C,OAKF,IAAM0B,EADc1B,EAAS,QAAQ,IAAI,cAAc,GACpB,SAAS,kBAAkB,EAC1D,MAAMA,EAAS,KAAK,EAAE,MAAM,IAAG,EAAY,EAC3C,OAEJ,GAAI,CAACA,EAAS,GAAI,CAChB,IAAM2B,EACJD,GACA,OAAOA,GAAS,UAChB,YAAaA,GACb,OAAOA,EAAK,SAAY,SACpBA,EAAK,QACL,8BAA8B1B,EAAS,MAAM,GAC7CC,EAAc,KAAK,iBAAiB,KAAMD,EAAS,MAAM,EAQ/D,GAPAuB,EAAY,IAAI1B,EACd8B,EACA3B,EAAS,OACT0B,EACAzB,CACF,EAEIA,GAAeU,EAAUW,EAAc,EAAG,CAC5C,MAAM,KAAK,MAAM,KAAK,cAAcX,CAAO,CAAC,EAC5C,QACF,CAEA,MAAMY,CACR,CAEA,OAAOG,CACT,OAASX,EAAO,CAGd,GAFA,aAAaU,CAAS,EAElBV,aAAiBlB,EAAe,CAClC,GAAI,CAACkB,EAAM,aAAeJ,GAAWW,EAAc,EACjD,MAAMP,EAERQ,EAAYR,EACZ,MAAM,KAAK,MAAM,KAAK,cAAcJ,CAAO,CAAC,EAC5C,QACF,CAEA,IAAMV,EAAc,KAAK,iBAAiBc,CAAK,EAC/C,GAAIA,aAAiB,MAAO,CAC1B,IAAMjB,EACJiB,EAAM,OAAS,aAAe,kBAAoBA,EAAM,QAQ1D,GAPAQ,EAAY,IAAI1B,EACdC,EACA,OACA,OACAG,CACF,EAEIA,GAAeU,EAAUW,EAAc,EAAG,CAC5C,MAAM,KAAK,MAAM,KAAK,cAAcX,CAAO,CAAC,EAC5C,QACF,CAEA,MAAMY,CACR,CAEA,MAAM,IAAI1B,EAAc,wBAAwB,CAClD,CACF,CAEA,MAAM0B,GAAa,IAAI1B,EAAc,8BAA8B,CACrE,CAEA,MAAM,IACJsB,EACAC,EACY,CACZ,OAAO,KAAK,QAAWD,EAAU,CAAE,GAAGC,EAAS,OAAQ,KAAM,CAAC,CAChE,CAEA,MAAM,KACJD,EACAS,EACAR,EACY,CACZ,OAAO,KAAK,QAAWD,EAAU,CAAE,GAAGC,EAAS,OAAQ,OAAQ,KAAAQ,CAAK,CAAC,CACvE,CAEA,MAAM,IACJT,EACAS,EACAR,EACY,CACZ,OAAO,KAAK,QAAWD,EAAU,CAAE,GAAGC,EAAS,OAAQ,MAAO,KAAAQ,CAAK,CAAC,CACtE,CAEA,MAAM,OACJT,EACAC,EACY,CACZ,OAAO,KAAK,QAAWD,EAAU,CAAE,GAAGC,EAAS,OAAQ,QAAS,CAAC,CACnE,CAOA,MAAM,YACJD,EACAU,EACAC,EAAY,QACA,CACZ,IAAMR,EAAc,KAAK,YAAY,WAAa,EAC9CC,EAEJ,QAASZ,EAAU,EAAGA,EAAUW,EAAaX,IAAW,CACtD,IAAMoB,EAAW,IAAI,SACrBF,EAAM,QAASG,GAAS,CACtBD,EAAS,OAAOD,EAAWE,CAAI,CACjC,CAAC,EAED,IAAMR,EAAa,IAAI,gBACjBC,EAAY,WAAW,IAAMD,EAAW,MAAM,EAAG,KAAK,QAAU,CAAC,EAEvE,GAAI,CACF,IAAMxB,EAAW,MAAM,MAAM,GAAG,KAAK,OAAO,GAAGmB,CAAQ,GAAI,CACzD,OAAQ,OACR,QAAS,CACP,cAAe,UAAU,KAAK,SAAS,EACzC,EACA,KAAMY,EACN,OAAQP,EAAW,MACrB,CAAC,EAID,GAFA,aAAaC,CAAS,EAGpBzB,EAAS,SAAW,KACpBA,EAAS,QAAQ,IAAI,gBAAgB,IAAM,IAE3C,OAIF,IAAM0B,EADc1B,EAAS,QAAQ,IAAI,cAAc,GACpB,SAAS,kBAAkB,EAC1D,MAAMA,EAAS,KAAK,EAAE,MAAM,IAAG,EAAY,EAC3C,OAEJ,GAAI,CAACA,EAAS,GAAI,CAChB,IAAM2B,EACJD,GACA,OAAOA,GAAS,UAChB,YAAaA,GACb,OAAOA,EAAK,SAAY,SACpBA,EAAK,QACL,6BAA6B1B,EAAS,MAAM,GAC5CC,EAAc,KAAK,iBAAiB,KAAMD,EAAS,MAAM,EAQ/D,GAPAuB,EAAY,IAAI1B,EACd8B,EACA3B,EAAS,OACT0B,EACAzB,CACF,EAEIA,GAAeU,EAAUW,EAAc,EAAG,CAC5C,MAAM,KAAK,MAAM,KAAK,cAAcX,CAAO,CAAC,EAC5C,QACF,CAEA,MAAMY,CACR,CAEA,OAAOG,CACT,OAASX,EAAO,CAGd,GAFA,aAAaU,CAAS,EAElBV,aAAiBlB,EAAe,CAClC,GAAI,CAACkB,EAAM,aAAeJ,GAAWW,EAAc,EACjD,MAAMP,EAERQ,EAAYR,EACZ,MAAM,KAAK,MAAM,KAAK,cAAcJ,CAAO,CAAC,EAC5C,QACF,CAEA,IAAMV,EAAc,KAAK,iBAAiBc,CAAK,EAC/C,GAAIA,aAAiB,MAAO,CAC1B,IAAMjB,EACJiB,EAAM,OAAS,aAAe,iBAAmBA,EAAM,QAQzD,GAPAQ,EAAY,IAAI1B,EACdC,EACA,OACA,OACAG,CACF,EAEIA,GAAeU,EAAUW,EAAc,EAAG,CAC5C,MAAM,KAAK,MAAM,KAAK,cAAcX,CAAO,CAAC,EAC5C,QACF,CAEA,MAAMY,CACR,CAEA,MAAM,IAAI1B,EAAc,wBAAwB,CAClD,CACF,CAEA,MAAM0B,GAAa,IAAI1B,EAAc,6BAA6B,CACpE,CACF,EC1VO,SAASoC,EACdC,EAC2B,CAC3B,OAAI,OAAOA,GAAU,SAAiBA,EAC/BA,EAAM,KAAK,EAAE,YAAY,CAClC,CAMO,SAASC,EACdC,EACG,CACH,OAAI,OAAOA,EAAM,OAAU,SAAiB,CAAE,GAAGA,CAAM,EAChD,CAAE,GAAGA,EAAO,MAAOA,EAAM,MAAM,KAAK,EAAE,YAAY,CAAE,CAC7D,CAKO,SAASC,EAEdD,EAAa,CACb,OAAI,OAAOA,EAAM,aAAgB,SAAiB,CAAE,GAAGA,CAAM,EACtD,CAAE,GAAGA,EAAO,YAAaA,EAAM,YAAY,KAAK,EAAE,YAAY,CAAE,CACzE,CCxBA,SAASE,EAAsBC,EAAoE,CACjG,OAAOA,GAAc,IAAIC,CAAmB,CAC9C,CAEO,IAAMC,EAAN,KAAgB,CACrB,YAAoBC,EAAoB,CAApB,YAAAA,CAAqB,CAMzC,MAAM,OAAOC,EAAyD,CACpE,OAAO,KAAK,OAAO,KAAuB,oBAAqB,CAC7D,GAAGA,EACH,aAAcL,EAAsBK,EAAO,YAAY,CACzD,CAAC,CACH,CAMA,MAAM,OAAOC,EAAoBD,EAAyD,CACxF,OAAO,KAAK,OAAO,IAAsB,qBAAqBC,CAAU,GAAID,CAAM,CACpF,CAKA,MAAM,aAAaC,EAAoBD,EAA+D,CACpG,OAAO,KAAK,OAAO,IAAsB,qBAAqBC,CAAU,UAAW,CACjF,GAAGD,EACH,aAAcL,EAAsBK,EAAO,YAAY,CACzD,CAAC,CACH,CAKA,MAAM,OAAOA,EAA+D,CAC1E,OAAO,KAAK,OAAO,KAA6B,2BAA4BA,CAAM,CACpF,CAKA,MAAM,sBAAsBE,EAAoD,CAC9E,OAAO,KAAK,OAAO,IAA4B,8BAA8BA,CAAS,eAAe,CACvG,CACF,ECjDO,IAAMC,EAAN,KAAiB,CACtB,YAAoBC,EAAoB,CAApB,YAAAA,CAAqB,CASzC,MAAM,cAAcC,EAAyE,CAC3F,OAAO,KAAK,OAAO,KAA+B,8BAA+B,CAC/E,GAAGA,EACH,WAAYA,EAAO,WAAW,IAAIC,CAAmB,EACrD,OAAQD,EAAO,QAAQ,IAAIE,CAAyB,EACpD,SAAUF,EAAO,SAAS,YAAY,CACxC,CAAC,CACH,CAKA,MAAM,iBAAiBG,EAAoD,CACzE,OAAO,KAAK,OAAO,IAA4B,+BAA+BA,CAAS,SAAS,CAClG,CAKA,MAAM,cAAcC,EAA+D,CACjF,IAAMJ,EAAS,IAAI,gBACfI,GAAY,YAAYJ,EAAO,IAAI,aAAc,OAAOI,EAAW,UAAU,CAAC,EAC9EA,GAAY,UAAUJ,EAAO,IAAI,WAAY,OAAOI,EAAW,QAAQ,CAAC,EAE5E,IAAMC,EAAQL,EAAO,SAAS,EAC9B,OAAO,KAAK,OAAO,IAA2B,8BAA8BK,EAAQ,IAAIA,CAAK,GAAK,EAAE,EAAE,CACxG,CAMA,MAAM,KAAKL,EAAiH,CAC1H,OAAO,KAAK,OAAO,KAAK,0BAA2BA,CAAM,CAC3D,CAKA,MAAM,cAAcI,EAA+D,CACjF,IAAMJ,EAAS,IAAI,gBACfI,GAAY,YAAYJ,EAAO,IAAI,aAAc,OAAOI,EAAW,UAAU,CAAC,EAC9EA,GAAY,UAAUJ,EAAO,IAAI,WAAY,OAAOI,EAAW,QAAQ,CAAC,EAE5E,IAAMC,EAAQL,EAAO,SAAS,EAC9B,OAAO,KAAK,OAAO,IAA2B,qBAAqBK,EAAQ,IAAIA,CAAK,GAAK,EAAE,EAAE,CAC/F,CACF,ECpDO,IAAMC,EAAN,KAAgB,CACrB,YAAoBC,EAAoB,CAApB,YAAAA,CAAqB,CAOzC,MAAM,OAAOC,EAAyD,CACpE,OAAO,KAAK,OAAO,KAAuB,oBAAqB,CAC7D,GAAGA,EACH,WAAYC,EAAoBD,EAAO,UAAU,CACnD,CAAC,CACH,CAMA,MAAM,KAAKA,EAA4D,CACrE,IAAME,EAAQ,IAAI,gBACdF,GAAQ,MAAME,EAAM,IAAI,OAAQ,OAAOF,EAAO,IAAI,CAAC,EACnDA,GAAQ,OAAOE,EAAM,IAAI,QAAS,OAAOF,EAAO,KAAK,CAAC,EACtDA,GAAQ,QAAQE,EAAM,IAAI,SAAUF,EAAO,MAAM,EACjDA,GAAQ,QAAQE,EAAM,IAAI,SAAUF,EAAO,MAAM,EAErD,IAAMG,EAAKD,EAAM,SAAS,EAC1B,OAAO,KAAK,OAAO,IAA0B,oBAAoBC,EAAK,IAAIA,CAAE,GAAK,EAAE,EAAE,CACvF,CAMA,MAAM,IAAIC,EAA+C,CACvD,OAAO,KAAK,OAAO,IAAsB,qBAAqBA,CAAU,EAAE,CAC5E,CAMA,MAAM,UAAUA,EAAqD,CACnE,OAAO,KAAK,OAAO,IAA4B,qBAAqBA,CAAU,SAAS,CACzF,CAMA,MAAM,cAAcA,EAAoBJ,EAAgE,CACtG,IAAME,EAAQ,IAAI,gBACdF,GAAQ,MAAME,EAAM,IAAI,OAAQ,OAAOF,EAAO,IAAI,CAAC,EACnDA,GAAQ,OAAOE,EAAM,IAAI,QAAS,OAAOF,EAAO,KAAK,CAAC,EAE1D,IAAMG,EAAKD,EAAM,SAAS,EAC1B,OAAO,KAAK,OAAO,IACjB,qBAAqBE,CAAU,cAAcD,EAAK,IAAIA,CAAE,GAAK,EAAE,EACjE,CACF,CAMA,MAAM,gBAAgBC,EAAoBJ,EAAuD,CAC/F,OAAO,KAAK,OAAO,KAAuB,qBAAqBI,CAAU,iBAAkBJ,CAAM,CACnG,CAMA,MAAM,KAAKI,EAAoBJ,EAA4D,CACzF,OAAO,KAAK,OAAO,KAA2B,qBAAqBI,CAAU,QAAS,CACpF,GAAGJ,EACH,SAAUA,GAAQ,UAAU,YAAY,CAC1C,CAAC,CACH,CAMA,MAAM,OAAOI,EAAqD,CAChE,OAAO,KAAK,OAAO,KAA6B,qBAAqBA,CAAU,UAAW,CAAC,CAAC,CAC9F,CAQA,MAAM,UAAUA,EAAoBJ,EAAmE,CACrG,OAAO,KAAK,OAAO,KACjB,qBAAqBI,CAAU,aAC/BJ,GAAU,CAAC,CACb,CACF,CACF,EC1GO,IAAMK,EAAN,KAAgB,CACrB,YAAoBC,EAAoB,CAApB,YAAAA,CAAqB,CAKzC,MAAM,eACJC,EACAC,EACmC,CACnC,OAAO,KAAK,OAAO,KAA+B,qBAAqBD,CAAU,aAAcC,CAAM,CACvG,CAKA,MAAM,eACJD,EACAC,EAC2C,CAC3C,OAAO,KAAK,OAAO,KACjB,qBAAqBD,CAAU,sBAC/B,CACE,GAAGC,EACH,gBAAiBA,EAAO,gBAAgB,IAAIC,CAAmB,CACjE,CACF,CACF,CAKA,MAAM,eACJF,EACAC,EACmC,CACnC,OAAO,KAAK,OAAO,KAA+B,qBAAqBD,CAAU,aAAc,CAC7F,GAAGC,EACH,WAAYC,EAAoBD,EAAO,UAAU,CACnD,CAAC,CACH,CACF,ECzCO,IAAME,EAAN,KAAe,CACpB,YAAoBC,EAAoB,CAApB,YAAAA,CAAqB,CAKzC,MAAM,OAAOC,EAAoBC,EAAuD,CACtF,OAAO,KAAK,OAAO,KAAsB,qBAAqBD,CAAU,YAAaC,CAAM,CAC7F,CAKA,MAAM,KAAKD,EAAoBC,EAA0D,CACvF,IAAMC,EAAQ,IAAI,gBACdD,GAAQ,MAAMC,EAAM,IAAI,OAAQ,OAAOD,EAAO,IAAI,CAAC,EACnDA,GAAQ,OAAOC,EAAM,IAAI,QAAS,OAAOD,EAAO,KAAK,CAAC,EACtDA,GAAQ,QAAQC,EAAM,IAAI,SAAUD,EAAO,MAAM,EACjDA,GAAQ,MAAMC,EAAM,IAAI,OAAQD,EAAO,IAAI,EAC3C,OAAOA,GAAQ,SAAY,WAAWC,EAAM,IAAI,UAAW,OAAOD,EAAO,OAAO,CAAC,EACjFA,GAAQ,aAAaC,EAAM,IAAI,cAAeD,EAAO,WAAW,EAChEA,GAAQ,WAAWC,EAAM,IAAI,YAAaD,EAAO,SAAS,EAE9D,IAAME,EAAKD,EAAM,SAAS,EAC1B,OAAO,KAAK,OAAO,IACjB,qBAAqBF,CAAU,YAAYG,EAAK,IAAIA,CAAE,GAAK,EAAE,EAC/D,CACF,CAKA,MAAM,IAAIH,EAAoBI,EAA6C,CACzE,OAAO,KAAK,OAAO,IAAqB,qBAAqBJ,CAAU,aAAaI,CAAS,EAAE,CACjG,CAKA,MAAM,KACJJ,EACAI,EACAH,EACgC,CAChC,OAAO,KAAK,OAAO,KACjB,qBAAqBD,CAAU,aAAaI,CAAS,QACrDH,GAAU,CAAC,CACb,CACF,CAKA,MAAM,OAAOD,EAAoBI,EAAmD,CAClF,OAAO,KAAK,OAAO,KACjB,qBAAqBJ,CAAU,aAAaI,CAAS,UACrD,CAAC,CACH,CACF,CAKA,MAAM,SACJJ,EACAI,EACAH,EAC0B,CAC1B,OAAO,KAAK,OAAO,KACjB,qBAAqBD,CAAU,aAAaI,CAAS,aACrDH,GAAU,CAAC,CACb,CACF,CACF,ECjFO,IAAMI,EAAN,KAAmB,CACxB,YAAoBC,EAAoB,CAApB,YAAAA,CAAqB,CAKzC,MAAM,eAAeC,EAAsD,CACzE,OAAO,KAAK,OAAO,IAA6B,qBAAqBA,CAAU,eAAe,CAChG,CAKA,MAAM,IAAIC,EAAqD,CAC7D,OAAO,KAAK,OAAO,IAAyB,wBAAwBA,CAAa,EAAE,CACrF,CACF,ECZO,IAAMC,EAAN,KAAe,CACpB,YAAoBC,EAAoB,CAApB,YAAAA,CAAqB,CAwBzC,MAAM,cAAcC,EAAuE,CACzF,OAAO,KAAK,OAAO,KAA8B,4BAA6B,CAC5E,GAAGA,EACH,MAAOC,EAAeD,EAAO,KAAK,CACpC,CAAC,CACH,CACF,ECnCO,IAAME,EAAN,KAAY,CACjB,YAAoBC,EAAoB,CAApB,YAAAA,CAAqB,CA6BzC,MAAM,OAAOC,EAAsD,CACjE,OAAO,KAAK,OAAO,YAAiC,uBAAwBA,CAAK,CACnF,CACF,ECpBA,OAAS,cAAAC,EAAY,mBAAAC,MAAuB,SAI5C,IAAMC,EAAuB,IAAS,IAEzBC,EAAN,KAAe,CAUpB,OAAO,OACLC,EACAC,EACAC,EACAC,EAC2B,CAC3B,GAAI,CAACH,GAAW,CAACC,GAAa,CAACC,GAAa,CAACC,EAC3C,MAAO,CAAE,MAAO,EAAM,EAIxB,IAAMC,EAAe,IAAI,KAAKF,CAAS,EAAE,QAAQ,EACjD,GAAI,MAAME,CAAY,EACpB,MAAO,CAAE,MAAO,EAAM,EAIxB,GADY,KAAK,IAAI,KAAK,IAAI,EAAIA,CAAY,EACpCN,EACR,MAAO,CAAE,MAAO,EAAM,EAIxB,IAAMO,EAAQJ,EAAU,MAAM,mBAAmB,EACjD,GAAI,CAACI,GAAS,CAACA,EAAM,CAAC,EACpB,MAAO,CAAE,MAAO,EAAM,EAExB,IAAMC,EAAsBD,EAAM,CAAC,EAG7BE,EAAe,GAAGL,CAAS,IAAIF,CAAO,GACtCQ,EAAcZ,EAAW,SAAUO,CAAM,EAC5C,OAAOI,CAAY,EACnB,OAAO,KAAK,EAGf,GAAID,EAAY,SAAWE,EAAY,OACrC,MAAO,CAAE,MAAO,EAAM,EAGxB,IAAMC,EAAI,OAAO,KAAKH,EAAa,KAAK,EAClCI,EAAI,OAAO,KAAKF,EAAa,KAAK,EAExC,GAAIC,EAAE,SAAWC,EAAE,OACjB,MAAO,CAAE,MAAO,EAAM,EAGxB,GAAI,CAACb,EAAgBY,EAAGC,CAAC,EACvB,MAAO,CAAE,MAAO,EAAM,EAIxB,GAAI,CAEF,MAAO,CAAE,MAAO,GAAM,SADY,KAAK,MAAMV,CAAO,CACrB,CACjC,MAAQ,CACN,MAAO,CAAE,MAAO,EAAM,CACxB,CACF,CAMA,OAAO,MACLA,EACoB,CACpB,OAAO,KAAK,MAAMA,CAAO,CAC3B,CACF,ECnDO,IAAMW,EAAN,KAAe,CACZ,OAUR,OAAuB,SAAWC,EAMlB,UAMA,WAMA,UAMA,UAMA,SAMA,aAMA,SAMA,MAEhB,YAAYC,EAAwB,CAClC,KAAK,OAAS,IAAIC,EAAWD,CAAM,EAEnC,KAAK,UAAY,IAAIE,EAAU,KAAK,MAAM,EAC1C,KAAK,WAAa,IAAIC,EAAW,KAAK,MAAM,EAC5C,KAAK,UAAY,IAAIC,EAAU,KAAK,MAAM,EAC1C,KAAK,UAAY,IAAIC,EAAU,KAAK,MAAM,EAC1C,KAAK,SAAW,IAAIC,EAAS,KAAK,MAAM,EACxC,KAAK,aAAe,IAAIC,EAAa,KAAK,MAAM,EAChD,KAAK,SAAW,IAAIC,EAAS,KAAK,MAAM,EACxC,KAAK,MAAQ,IAAIC,EAAM,KAAK,MAAM,CACpC,CAKA,MAAM,eAAqC,CACzC,OAAO,KAAK,OAAO,IAAgB,YAAY,CACjD,CAKA,MAAM,aAA4C,CAChD,OAAO,KAAK,OAAO,IAAyB,gBAAgB,CAC9D,CACF","names":["ChaindocError","message","statusCode","response","isRetryable","ENVIRONMENT_URLS","DEFAULT_ENVIRONMENT","DEFAULT_TIMEOUT","DEFAULT_MAX_RETRIES","DEFAULT_BASE_DELAY_MS","DEFAULT_MAX_DELAY_MS","HttpClient","config","environment","attempt","exponentialDelay","cappedDelay","jitter","error","e","ms","resolve","endpoint","options","url","maxAttempts","lastError","controller","timeoutId","data","errorMessage","body","files","fieldName","formData","file","normalizeEmail","value","withNormalizedEmail","input","withNormalizedSignerEmail","normalizeAccessEmails","accessEmails","withNormalizedEmail","Documents","client","params","documentId","versionId","Signatures","client","params","withNormalizedEmail","withNormalizedSignerEmail","requestId","pagination","query","Contracts","client","params","withNormalizedEmail","query","qs","contractId","Templates","client","templateId","params","withNormalizedEmail","Invoices","client","contractId","params","query","qs","invoiceId","Transactions","client","contractId","transactionId","Embedded","client","params","normalizeEmail","Media","client","files","createHmac","timingSafeEqual","MAX_TIMESTAMP_AGE_MS","Webhooks","rawBody","signature","timestamp","secret","deliveryTime","match","receivedHex","signingInput","expectedHex","a","b","Chaindoc","Webhooks","config","HttpClient","Documents","Signatures","Contracts","Templates","Invoices","Transactions","Embedded","Media"]}
{
"name": "@chaindoc_io/server-sdk",
"version": "2.0.0",
"version": "2.0.1",
"description": "Server-side SDK for Chaindoc API - document management, signatures, and embedded sessions",

@@ -5,0 +5,0 @@ "main": "./dist/index.cjs",

@@ -226,2 +226,6 @@ # @chaindoc_io/server-sdk

### Email handling
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.
## API Overview

@@ -228,0 +232,0 @@