diff --git a/docs/SDKs/go.md b/docs/SDKs/go.md new file mode 100644 index 0000000..d95ecd8 --- /dev/null +++ b/docs/SDKs/go.md @@ -0,0 +1,541 @@ +--- +title: Go SDK +sidebar_position: 4 +sidebar_label: Go +description: Official TurboDocx Go SDK. Idiomatic Go with context support for document generation and digital signatures. +keywords: + - turbodocx go + - turbosign go + - golang sdk + - go module + - document api go + - esignature golang +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Go SDK + +The official TurboDocx SDK for Go applications. Build document generation and digital signature workflows with idiomatic Go patterns, context support, and comprehensive error handling. Available as `github.com/TurboDocx/SDK/packages/go-sdk`. + +## Installation + +```bash +go get github.com/TurboDocx/SDK/packages/go-sdk +``` + +## Requirements + +- Go 1.21+ + +--- + +## Configuration + +```go +package main + +import ( + "os" + + turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" +) + +func main() { + // Create a new client + client, err := turbodocx.NewClient( + os.Getenv("TURBODOCX_API_KEY"), + os.Getenv("TURBODOCX_ORG_ID"), + ) + if err != nil { + log.Fatal(err) + } + + // Or with custom configuration + client, err := turbodocx.NewClientWithConfig(turbodocx.ClientConfig{ + APIKey: os.Getenv("TURBODOCX_API_KEY"), + OrgID: os.Getenv("TURBODOCX_ORG_ID"), + BaseURL: "https://api.turbodocx.com", // Optional custom base URL + }) +} +``` + +### Environment Variables + +```bash +export TURBODOCX_API_KEY=your_api_key_here +export TURBODOCX_ORG_ID=your_org_id_here +``` + +--- + +## Quick Start + +### Send a Document for Signature + +```go +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "os" + + turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" +) + +func main() { + client, err := turbodocx.NewClient( + os.Getenv("TURBODOCX_API_KEY"), + os.Getenv("TURBODOCX_ORG_ID"), + ) + if err != nil { + log.Fatal(err) + } + + ctx := context.Background() + + result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{ + FileLink: "https://example.com/contract.pdf", + DocumentName: "Service Agreement", + SenderName: "Acme Corp", + SenderEmail: "contracts@acme.com", + Recipients: []turbodocx.Recipient{ + {Name: "Alice Smith", Email: "alice@example.com", SigningOrder: 1}, + {Name: "Bob Johnson", Email: "bob@example.com", SigningOrder: 2}, + }, + Fields: []turbodocx.Field{ + // Alice's signature + {Type: "signature", Page: 1, X: 100, Y: 650, Width: 200, Height: 50, RecipientEmail: "alice@example.com"}, + {Type: "date", Page: 1, X: 320, Y: 650, Width: 100, Height: 30, RecipientEmail: "alice@example.com"}, + // Bob's signature + {Type: "signature", Page: 1, X: 100, Y: 720, Width: 200, Height: 50, RecipientEmail: "bob@example.com"}, + {Type: "date", Page: 1, X: 320, Y: 720, Width: 100, Height: 30, RecipientEmail: "bob@example.com"}, + }, + }) + if err != nil { + log.Fatal(err) + } + + b, _ := json.MarshalIndent(result, "", " "); fmt.Println("Result:", string(b)) +} +``` + +### Using Template-Based Fields + +```go +result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{ + FileLink: "https://example.com/contract-with-placeholders.pdf", + Recipients: []turbodocx.Recipient{ + {Name: "Alice Smith", Email: "alice@example.com", SigningOrder: 1}, + }, + Fields: []turbodocx.Field{ + { + Type: "signature", + RecipientEmail: "alice@example.com", + Template: &turbodocx.TemplateAnchor{ + Anchor: "{SIGNATURE_ALICE}", + Placement: "replace", + Size: &turbodocx.Size{Width: 200, Height: 50}, + }, + }, + { + Type: "date", + RecipientEmail: "alice@example.com", + Template: &turbodocx.TemplateAnchor{ + Anchor: "{DATE_ALICE}", + Placement: "replace", + Size: &turbodocx.Size{Width: 100, Height: 30}, + }, + }, + }, +}) +``` + +:::info Template Anchors Required +**Important:** The document file must contain the anchor text (e.g., `{SIGNATURE_ALICE}`, `{DATE_ALICE}`) that you reference in your fields. If the anchors don't exist in the document, the API will return an error. +::: + +--- + +## File Input Methods + +The SDK supports multiple ways to provide your document: + +### 1. File Upload ([]byte) + +Upload a document directly from file bytes: + +```go +pdfBytes, err := os.ReadFile("/path/to/document.pdf") +if err != nil { + log.Fatal(err) +} + +result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{ + File: pdfBytes, + Recipients: []turbodocx.Recipient{ + {Name: "John Doe", Email: "john@example.com", SigningOrder: 1}, + }, + Fields: []turbodocx.Field{ + {Type: "signature", Page: 1, X: 100, Y: 500, Width: 200, Height: 50, RecipientEmail: "john@example.com"}, + }, +}) +``` + +### 2. File URL + +Provide a publicly accessible URL to your document: + +```go +result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{ + FileLink: "https://example.com/documents/contract.pdf", + Recipients: []turbodocx.Recipient{ + {Name: "John Doe", Email: "john@example.com", SigningOrder: 1}, + }, + Fields: []turbodocx.Field{ + {Type: "signature", Page: 1, X: 100, Y: 500, Width: 200, Height: 50, RecipientEmail: "john@example.com"}, + }, +}) +``` + +:::tip When to use FileLink +Use `FileLink` when your documents are already hosted on cloud storage (S3, Google Cloud Storage, etc.). This is more efficient than downloading and re-uploading files. +::: + +### 3. TurboDocx Deliverable ID + +Use a document generated by TurboDocx document generation: + +```go +result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{ + DeliverableID: "deliverable-uuid-from-turbodocx", + Recipients: []turbodocx.Recipient{ + {Name: "John Doe", Email: "john@example.com", SigningOrder: 1}, + }, + Fields: []turbodocx.Field{ + {Type: "signature", Page: 1, X: 100, Y: 500, Width: 200, Height: 50, RecipientEmail: "john@example.com"}, + }, +}) +``` + +:::info Integration with TurboDocx +`DeliverableID` references documents generated using TurboDocx's document generation API. This creates a seamless workflow: generate → sign. +::: + +### 4. TurboDocx Template ID + +Use a pre-configured TurboDocx template: + +```go +result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{ + TemplateID: "template-uuid-from-turbodocx", + Recipients: []turbodocx.Recipient{ + {Name: "John Doe", Email: "john@example.com", SigningOrder: 1}, + }, + Fields: []turbodocx.Field{ + {Type: "signature", Page: 1, X: 100, Y: 500, Width: 200, Height: 50, RecipientEmail: "john@example.com"}, + }, +}) +``` + +:::info Integration with TurboDocx +`TemplateID` references pre-configured TurboSign templates created in the TurboDocx dashboard. These templates come with built-in anchors and field positioning, making it easy to reuse signature workflows across multiple documents. +::: + +--- + +## API Reference + +### Configure + +Create a new TurboDocx client. + +```go +// Simple initialization +client, err := turbodocx.NewClient(apiKey, orgID string) + +// With custom configuration +client, err := turbodocx.NewClientWithConfig(turbodocx.ClientConfig{ + APIKey: "your-api-key", + OrgID: "your-org-id", + BaseURL: "https://api.turbodocx.com", // Optional +}) +``` + +:::warning API Credentials Required +Both `APIKey` and `OrgID` parameters are **required** for all API requests. To get your credentials, follow the **[Get Your Credentials](/docs/SDKs#1-get-your-credentials)** steps from the SDKs main page. +::: + +### Prepare for review + +Upload a document for preview without sending emails. + +```go +result, err := client.TurboSign.CreateSignatureReviewLink(ctx, &turbodocx.CreateSignatureReviewLinkRequest{ + FileLink: "https://example.com/document.pdf", + DocumentName: "Contract Draft", + Recipients: []turbodocx.Recipient{ + {Name: "John Doe", Email: "john@example.com", SigningOrder: 1}, + }, + Fields: []turbodocx.Field{ + {Type: "signature", Page: 1, X: 100, Y: 500, Width: 200, Height: 50, RecipientEmail: "john@example.com"}, + }, +}) + +b, _ := json.MarshalIndent(result, "", " "); fmt.Println("Result:", string(b)) +``` + +### Prepare for signing + +Upload a document and immediately send signature requests. + +```go +result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{ + FileLink: "https://example.com/document.pdf", + DocumentName: "Service Agreement", + SenderName: "Your Company", + SenderEmail: "sender@company.com", + Recipients: []turbodocx.Recipient{ + {Name: "Recipient Name", Email: "recipient@example.com", SigningOrder: 1}, + }, + Fields: []turbodocx.Field{ + {Type: "signature", Page: 1, X: 100, Y: 500, Width: 200, Height: 50, RecipientEmail: "recipient@example.com"}, + }, +}) +``` + +### Get status + +Check the status of a document. + +```go +status, err := client.TurboSign.GetStatus(ctx, "document-uuid") +if err != nil { + log.Fatal(err) +} + +b, _ := json.MarshalIndent(status, "", " "); fmt.Println("Result:", string(b)) +``` + +### Download document + +Download the completed signed document. + +```go +pdfData, err := client.TurboSign.Download(ctx, "document-uuid") +if err != nil { + log.Fatal(err) +} + +// Save to file +err = os.WriteFile("signed-contract.pdf", pdfData, 0644) +if err != nil { + log.Fatal(err) +} +``` + +### Get audit trail + +Retrieve the audit trail for a document. + +```go +auditTrail, err := client.TurboSign.GetAuditTrail(ctx, "document-uuid") +if err != nil { + log.Fatal(err) +} + +b, _ := json.MarshalIndent(auditTrail, "", " "); fmt.Println("Result:", string(b)) +``` + +### Void + +Cancel/void a signature request. + +```go +result, err := client.TurboSign.VoidDocument(ctx, "document-uuid", "Contract terms changed") +``` + +### Resend + +Resend signature request emails. + +```go +// Resend to specific recipients +result, err := client.TurboSign.ResendEmail(ctx, "document-uuid", []string{"recipient-uuid-1", "recipient-uuid-2"}) +``` + +--- + +## Error Handling + +The SDK provides typed errors for different error scenarios: + +### Error Types + +| Error Type | Status Code | Description | +| --------------------- | ----------- | ---------------------------------- | +| `TurboDocxError` | varies | Base error type for all API errors | +| `AuthenticationError` | 401 | Invalid or missing API key | +| `ValidationError` | 400 | Invalid request parameters | +| `NotFoundError` | 404 | Resource not found | +| `RateLimitError` | 429 | Too many requests | +| `NetworkError` | - | Network connectivity issues | + +### Error Properties + +| Property | Type | Description | +| ------------ | -------- | ---------------------------- | +| `Message` | `string` | Human-readable error message | +| `StatusCode` | `int` | HTTP status code | +| `Code` | `string` | Error code (if available) | + +### Example + +```go +import ( + "errors" + + turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" +) + +result, err := client.TurboSign.SendSignature(ctx, request) +if err != nil { + // Check for specific error types + var authErr *turbodocx.AuthenticationError + var validationErr *turbodocx.ValidationError + var notFoundErr *turbodocx.NotFoundError + var rateLimitErr *turbodocx.RateLimitError + var networkErr *turbodocx.NetworkError + + switch { + case errors.As(err, &authErr): + log.Printf("Authentication failed: %s", authErr.Message) + case errors.As(err, &validationErr): + log.Printf("Validation error: %s", validationErr.Message) + case errors.As(err, ¬FoundErr): + log.Printf("Not found: %s", notFoundErr.Message) + case errors.As(err, &rateLimitErr): + log.Printf("Rate limited: %s", rateLimitErr.Message) + case errors.As(err, &networkErr): + log.Printf("Network error: %s", networkErr.Message) + default: + // Base TurboDocxError or unexpected error + var turboErr *turbodocx.TurboDocxError + if errors.As(err, &turboErr) { + log.Printf("API error [%d]: %s", turboErr.StatusCode, turboErr.Message) + } else { + log.Fatal(err) + } + } +} +``` + +--- + +## Types + +### Signature Field Types + +The `Type` field accepts the following string values: + +| Type | Description | +| -------------- | ---------------- | +| `"signature"` | Signature field | +| `"initials"` | Initials field | +| `"text"` | Text input field | +| `"date"` | Date field | +| `"checkbox"` | Checkbox field | +| `"full_name"` | Full name field | +| `"first_name"` | First name field | +| `"last_name"` | Last name field | +| `"email"` | Email field | +| `"title"` | Title field | +| `"company"` | Company field | + +### Recipient + +| Property | Type | Required | Description | +| -------------- | -------- | -------- | ------------------------------------------------- | +| `Name` | `string` | Yes | Recipient's full name | +| `Email` | `string` | Yes | Recipient's email address | +| `SigningOrder` | `int` | Yes | Order in which recipient should sign (1, 2, 3...) | + +### Field + +| Property | Type | Required | Description | +| ----------------- | ----------------- | -------- | ------------------------------------------- | +| `Type` | `string` | Yes | Field type (see table above) | +| `RecipientEmail` | `string` | Yes | Email of the recipient who fills this field | +| `Page` | `int` | No\* | Page number (1-indexed) | +| `X` | `int` | No\* | X coordinate in pixels | +| `Y` | `int` | No\* | Y coordinate in pixels | +| `Width` | `int` | No* | Field width in pixels | +| `Height` | `int` | No* | Field height in pixels | +| `DefaultValue` | `string` | No | Pre-filled value | +| `IsMultiline` | `bool` | No | Enable multiline for text fields | +| `IsReadonly` | `bool` | No | Make field read-only | +| `Required` | `bool` | No | Make field required | +| `BackgroundColor` | `string` | No | Background color | +| `Template` | `*TemplateAnchor` | No | Template anchor configuration | + +\*Required when not using template anchors + +#### Template Configuration + +When using `Template` instead of coordinates: + +| Property | Type | Required | Description | +| --------------- | -------- | -------- | ------------------------------------------------------------------------------------- | +| `Anchor` | `string` | Yes | Text to find in document (e.g., `"{SIGNATURE}"`) | +| `Placement` | `string` | Yes | Position relative to anchor: `"replace"`, `"before"`, `"after"`, `"above"`, `"below"` | +| `Size` | `*Size` | Yes | Size with `Width` and `Height` | +| `Offset` | `*Point` | No | Offset with `X` and `Y` | +| `CaseSensitive` | `bool` | No | Case-sensitive anchor search | +| `UseRegex` | `bool` | No | Use regex for anchor search | + +### Request Parameters + +Both `CreateSignatureReviewLinkRequest` and `SendSignatureRequest` accept: + +| Property | Type | Required | Description | +| --------------------- | ------------- | ----------- | ------------------------ | +| `File` | `[]byte` | Conditional | File content as bytes | +| `FileLink` | `string` | Conditional | URL to document | +| `DeliverableID` | `string` | Conditional | TurboDocx deliverable ID | +| `TemplateID` | `string` | Conditional | TurboDocx template ID | +| `Recipients` | `[]Recipient` | Yes | List of recipients | +| `Fields` | `[]Field` | Yes | List of fields | +| `DocumentName` | `string` | No | Document display name | +| `DocumentDescription` | `string` | No | Document description | +| `SenderName` | `string` | No | Sender's name | +| `SenderEmail` | `string` | No | Sender's email | +| `CCEmails` | `[]string` | No | CC email addresses | + +:::info File Source (Conditional) +Exactly one file source is required: `File`, `FileLink`, `DeliverableID`, or `TemplateID`. +::: + +--- + +## Additional Documentation + +For detailed information about advanced configuration and API concepts, see: + +### Core API References + +- **[Request Body Reference](/docs/TurboSign/API%20Signatures#request-body-multipartform-data)** - Complete request body parameters, file sources, and multipart/form-data structure +- **[Recipients Reference](/docs/TurboSign/API%20Signatures#recipients-reference)** - Recipient properties, signing order, metadata, and configuration options +- **[Field Types Reference](/docs/TurboSign/API%20Signatures#field-types-reference)** - All available field types (signature, date, text, checkbox, etc.) with properties and behaviors +- **[Field Positioning Methods](/docs/TurboSign/API%20Signatures#field-positioning-methods)** - Template-based vs coordinate-based positioning, anchor configuration, and best practices + +--- + +## Resources + +- [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/go-sdk) +- [API Reference](/docs/TurboSign/API-Signatures) +- [Webhook Configuration](/docs/TurboSign/Webhooks) diff --git a/docs/SDKs/index.md b/docs/SDKs/index.md new file mode 100644 index 0000000..caeb291 --- /dev/null +++ b/docs/SDKs/index.md @@ -0,0 +1,670 @@ +--- +title: SDKs Overview +sidebar_position: 1 +sidebar_label: Overview +description: Official TurboDocx SDKs for JavaScript, Python, Go, and Java. Get started with document generation and digital signatures in minutes. +keywords: + - turbodocx sdk + - turbosign sdk + - javascript sdk + - python sdk + - go sdk + - java sdk + - document api + - esignature sdk + - api client library +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# TurboDocx SDKs + +Official client libraries for the TurboDocx API. Build document generation and digital signature workflows in your language of choice. + +## Available SDKs + +| Language | Package | Install Command | Links | +| :------------------------ | :------------------------- | :------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- | +| **JavaScript/TypeScript** | `@turbodocx/sdk` | `npm install @turbodocx/sdk` | [Docs](/docs/SDKs/javascript) [GitHub](https://github.com/TurboDocx/SDK/tree/main/packages/js-sdk) | +| **Python** | `turbodocx-sdk` | `pip install turbodocx-sdk` | [Docs](/docs/SDKs/python) [GitHub](https://github.com/TurboDocx/SDK/tree/main/packages/py-sdk) | +| **Go** | `github.com/turbodocx/sdk` | `go get github.com/turbodocx/sdk` | [Docs](/docs/SDKs/go) [GitHub](https://github.com/TurboDocx/SDK/tree/main/packages/go-sdk) | +| **Java** | `com.turbodocx:sdk` | [Maven Central](https://search.maven.org/artifact/com.turbodocx/sdk) | [Docs](/docs/SDKs/java) [GitHub](https://github.com/TurboDocx/SDK/tree/main/packages/java-sdk) | + +:::tip Low-code or No-code? +Check out our [n8n community node](https://www.npmjs.com/package/@turbodocx/n8n-nodes-turbodocx) for workflow automation, or get [TurboDocx Writer](https://appsource.microsoft.com/en-us/product/office/WA200007397) for Microsoft Word. +::: + +--- + +## Quick Start + +Get up and running in under 2 minutes. + +### 1. Get Your Credentials + +Before you begin, you'll need two things from your TurboDocx account: + +- **API Access Token**: Your authentication key +- **Organization ID**: Your unique organization identifier + +#### How to Get Your Credentials + +1. **Login to TurboDocx**: Visit [https://www.turbodocx.com](https://www.turbodocx.com) +2. **Navigate to Settings**: Access your organization settings +3. **API Keys Section**: Generate or copy your API access token +4. **Organization ID**: Copy your organization ID from the same settings page + +![TurboSign API Key](/img/turbosign/api/api-key.png) +![TurboSign Organization ID](/img/turbosign/api/org-id.png) + +:::tip Keep Your Credentials Secure + +- Store your API key and Organization ID as environment variables +- Never commit credentials to version control +- Rotate your API keys regularly for security +::: + +### 2. Install the SDK + + + + +```bash +npm install @turbodocx/sdk +# or +yarn add @turbodocx/sdk +# or +pnpm add @turbodocx/sdk +``` + + + + +```bash +npm install @turbodocx/sdk +# or +yarn add @turbodocx/sdk +# or +pnpm add @turbodocx/sdk + +# TypeScript types are included in the package +``` + + + + +```bash +pip install turbodocx-sdk +# or +poetry add turbodocx-sdk +``` + + + + +```bash +go get github.com/turbodocx/sdk +``` + + + + +```xml + + com.turbodocx + sdk + 1.0.0 + +``` + + + + +### 3. Send Your First Document for Signature + + + + +```javascript +const { TurboSign } = require("@turbodocx/sdk"); +// or with ES modules: +// import { TurboSign } from '@turbodocx/sdk'; + +// Configure with your API key +TurboSign.configure({ + apiKey: process.env.TURBODOCX_API_KEY, + orgId: process.env.TURBODOCX_ORG_ID, +}); + +// Send a document for signature +const result = await TurboSign.sendSignature({ + fileLink: "https://example.com/contract.pdf", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 500, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); + +console.log(`Document sent! ID: ${result.documentId}`); +``` + + + + +```typescript +import { TurboSign } from "@turbodocx/sdk"; + +// Configure with your API key +TurboSign.configure({ + apiKey: process.env.TURBODOCX_API_KEY || "", + orgId: process.env.TURBODOCX_ORG_ID || "", +}); + +// Send a document for signature +const result = await TurboSign.sendSignature({ + fileLink: "https://example.com/contract.pdf", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 500, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); + +console.log(`Document sent! ID: ${result.documentId}`); +``` + + + + +```python +from turbodocx import TurboSign +import os + +# Configure with your API key +TurboSign.configure( + api_key=os.environ["TURBODOCX_API_KEY"], + org_id=os.environ["TURBODOCX_ORG_ID"] +) + +# Send a document for signature +result = TurboSign.send_signature( + file_link="https://example.com/contract.pdf", + recipients=[ + {"name": "John Doe", "email": "john@example.com", "signingOrder": 1} + ], + fields=[ + {"type": "signature", "page": 1, "x": 100, "y": 500, "width": 200, "height": 50, "recipientEmail": "john@example.com"} + ] +) + +print(f"Document sent! ID: {result.documentId}") +``` + + + + +```go +package main + +import ( + "context" + "fmt" + "os" + + "github.com/turbodocx/sdk" +) + +func main() { + // Configure with your API key + client := sdk.NewTurboSign( + os.Getenv("TURBODOCX_API_KEY"), + os.Getenv("TURBODOCX_ORG_ID"), + ) + + // Send a document for signature + result, err := client.TurboSign.SendSignature(context.Background(), &sdk.SendSignatureRequest{ + FileLink: "https://example.com/contract.pdf", + Recipients: []sdk.Recipient{ + {Name: "John Doe", Email: "john@example.com", SigningOrder: 1}, + }, + Fields: []sdk.Field{ + {Type: "signature", Page: 1, X: 100, Y: 500, Width: 200, Height: 50, RecipientEmail: "john@example.com"}, + }, + }) + if err != nil { + panic(err) + } + + fmt.Printf("Document sent! ID: %s\n", result.documentId) +} +``` + + + + +```java +import com.turbodocx.sdk.TurboSign; +import com.turbodocx.sdk.models.*; + +public class Main { + public static void main(String[] args) { + // Configure with your API key + TurboSign turboSign = new TurboSign( + System.getenv("TURBODOCX_API_KEY"), + System.getenv("TURBODOCX_ORG_ID") + ); + + // Send a document for signature + SigningResult result = turboSign.sendSignature( + SigningRequest.builder() + .fileLink("https://example.com/contract.pdf") + .recipient(Recipient.builder() + .name("John Doe") + .email("john@example.com") + .signingOrder(1) + .build()) + .field(Field.builder() + .type("signature") + .page(1).x(100).y(500).width(200).height(50) + .recipientEmail("john@example.com") + .build()) + .build() + ); + + System.out.println("Document sent! ID: " + result.documentId); + } +} +``` + + + + +--- + +## Core Features + +All TurboDocx SDKs provide access to: + +### TurboSign — Digital Signatures + +Send documents for legally-binding eSignatures with full audit trails. + +| Method | Description | +| :---------------------------- | :------------------------------------------------------ | +| `createSignatureReviewLink()` | Upload document for preview without sending emails | +| `sendSignature()` | Upload and immediately send signature requests | +| `getStatus()` | Check document and recipient signing status | +| `download()` | Download the completed signed document | +| `void()` | Cancel/void a signature request | +| `resend()` | Resend signature request emails | +| `getAuditTrail()` | Get complete audit trail with all events and timestamps | + +[Learn more about TurboSign →](/docs/TurboSign/Setting%20up%20TurboSign) + +### TurboDocx — Document Generation _(Coming Soon)_ + +Generate documents from templates with dynamic data. + +--- + +## Field Positioning + +TurboSign supports two methods for placing signature fields on your documents: + +| Method | Best For | +| :------------------- | :----------------------------------------------------------------------- | +| **Coordinate-Based** | PDFs with fixed layouts where you know exact pixel positions | +| **Template-Based** | Documents where content may shift, using text anchors like `{SIGNATURE}` | + +:::info Field Positioning Reference +For detailed information about both positioning methods, including anchor configuration, placement options, and best practices, see the **[Field Positioning Methods](/docs/TurboSign/API%20Signatures#field-positioning-methods)** guide. +::: + +:::info Complete Field Types Reference +For a comprehensive list of all available field types (signature, initials, text, date, checkbox, full_name, email, title, company) and their detailed usage, see the [Field Types section in the API Signatures guide](/docs/TurboSign/API%20Signatures#field-types-reference). +::: + +--- + +## Error Handling + +All SDKs provide structured error handling with detailed error codes: + + + + +```javascript +const { TurboSign, TurboDocxError } = require("@turbodocx/sdk"); + +try { + const result = await TurboSign.sendSignature({ + /* ... */ + }); +} catch (error) { + if (error instanceof TurboDocxError) { + console.error(`Error ${error.code}: ${error.message}`); + // Handle specific error codes + if (error.code === "VALIDATION_ERROR") { + // Handle validation error + } + } +} +``` + + + + +```typescript +import { TurboSign, TurboDocxError } from "@turbodocx/sdk"; + +try { + const result = await TurboSign.sendSignature({ + /* ... */ + }); +} catch (error) { + if (error instanceof TurboDocxError) { + console.error(`Error ${error.code}: ${error.message}`); + // Handle specific error codes + if (error.code === "VALIDATION_ERROR") { + // Handle validation error + } + } +} +``` + + + + +```python +from turbodocx import TurboSign +from turbodocx.exceptions import TurboDocxError + +try: + result = await TurboSign.send_signature(...) +except TurboDocxError as e: + print(f"Error {e.code}: {e.message}") + if e.code == "VALIDATION_ERROR": + # Handle validation error + pass +``` + + + + +```go +result, err := client.TurboSign.SendSignature(ctx, request) +if err != nil { + var turboErr *sdk.TurboDocxError + if errors.As(err, &turboErr) { + fmt.Printf("Error %s: %s\n", turboErr.Code, turboErr.Message) + if turboErr.Code == "VALIDATION_ERROR" { + // Handle validation error + } + } +} +``` + + + + +```java +import com.turbodocx.sdk.TurboSign; +import com.turbodocx.sdk.TurboDocxException; +import com.turbodocx.sdk.TurboDocxException.*; + +try { + SigningResult result = turboSign.sendSignature(/* ... */); +} catch (AuthenticationException e) { + System.err.println("Invalid API key: " + e.getMessage()); +} catch (ValidationException e) { + System.err.println("Validation error: " + e.getMessage()); + System.err.println("Error code: " + e.getCode()); +} catch (RateLimitException e) { + System.err.println("Rate limited: " + e.getMessage()); +} catch (TurboDocxException e) { + System.err.println("Error " + e.getCode() + ": " + e.getMessage()); + System.err.println("Status code: " + e.getStatusCode()); +} +``` + + + + +### Common Error Codes + +| Code | HTTP Status | Description | +| :--------------------- | :---------- | :------------------------------------ | +| `AUTHENTICATION_ERROR` | 401 | Invalid or expired API key | +| `VALIDATION_ERROR` | 400 | Invalid request data or parameters | +| `NOT_FOUND` | 404 | Document or resource not found | +| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests, retry with backoff | +| `NETWORK_ERROR` | N/A | Network connection or timeout error | + +--- + +## Next Steps + +
+
+
{ + e.currentTarget.style.transform = 'translateY(-8px)'; + e.currentTarget.style.boxShadow = '0 12px 24px rgba(0, 0, 0, 0.2), 0 6px 12px rgba(0, 0, 0, 0.15)'; + }} + onMouseOut={(e) => { + e.currentTarget.style.transform = 'translateY(0)'; + e.currentTarget.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.06)'; + }} + > +
+

API Signatures

+
+
+

Complete guide to TurboSign API integration with detailed examples.

+
+
+ { + e.currentTarget.style.transform = 'scale(1.02)'; + e.currentTarget.style.boxShadow = '0 6px 20px rgba(0, 0, 0, 0.25)'; + e.currentTarget.style.background = 'linear-gradient(135deg, var(--ifm-color-primary-dark) 0%, var(--ifm-color-primary-darker) 100%)'; + }} + onMouseOut={(e) => { + e.currentTarget.style.transform = 'scale(1)'; + e.currentTarget.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)'; + e.currentTarget.style.background = 'linear-gradient(135deg, var(--ifm-color-primary) 0%, var(--ifm-color-primary-dark) 100%)'; + }} + > + View Guide → + +
+
+
+
+
{ + e.currentTarget.style.transform = 'translateY(-8px)'; + e.currentTarget.style.boxShadow = '0 12px 24px rgba(0, 0, 0, 0.2), 0 6px 12px rgba(0, 0, 0, 0.15)'; + }} + onMouseOut={(e) => { + e.currentTarget.style.transform = 'translateY(0)'; + e.currentTarget.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.06)'; + }} + > +
+

Webhooks

+
+
+

Receive real-time notifications when documents are signed.

+
+
+ { + e.currentTarget.style.transform = 'scale(1.02)'; + e.currentTarget.style.boxShadow = '0 6px 20px rgba(0, 0, 0, 0.25)'; + e.currentTarget.style.background = 'linear-gradient(135deg, var(--ifm-color-primary-dark) 0%, var(--ifm-color-primary-darker) 100%)'; + }} + onMouseOut={(e) => { + e.currentTarget.style.transform = 'scale(1)'; + e.currentTarget.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)'; + e.currentTarget.style.background = 'linear-gradient(135deg, var(--ifm-color-primary) 0%, var(--ifm-color-primary-dark) 100%)'; + }} + > + Configure Webhooks → + +
+
+
+
+
{ + e.currentTarget.style.transform = 'translateY(-8px)'; + e.currentTarget.style.boxShadow = '0 12px 24px rgba(0, 0, 0, 0.2), 0 6px 12px rgba(0, 0, 0, 0.15)'; + }} + onMouseOut={(e) => { + e.currentTarget.style.transform = 'translateY(0)'; + e.currentTarget.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.06)'; + }} + > +
+

GitHub Repository

+
+
+

View source code, report issues, and contribute to the SDKs.

+
+
+ { + e.currentTarget.style.transform = 'scale(1.02)'; + e.currentTarget.style.boxShadow = '0 6px 20px rgba(0, 0, 0, 0.25)'; + e.currentTarget.style.background = 'linear-gradient(135deg, var(--ifm-color-primary-dark) 0%, var(--ifm-color-primary-darker) 100%)'; + }} + onMouseOut={(e) => { + e.currentTarget.style.transform = 'scale(1)'; + e.currentTarget.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)'; + e.currentTarget.style.background = 'linear-gradient(135deg, var(--ifm-color-primary) 0%, var(--ifm-color-primary-dark) 100%)'; + }} + > + View on GitHub → + +
+
+
+
+ +--- + +## Support + +Need help with the SDKs? + +- **Discord Community**: [Join our Discord](https://discord.gg/NYKwz4BcpX) for real-time support +- **GitHub Issues**: [Report bugs or request features](https://github.com/TurboDocx/SDK/issues) +- **Documentation**: Browse the language-specific guides in the sidebar diff --git a/docs/SDKs/java.md b/docs/SDKs/java.md new file mode 100644 index 0000000..ec453fe --- /dev/null +++ b/docs/SDKs/java.md @@ -0,0 +1,554 @@ +--- +title: Java SDK +sidebar_position: 6 +sidebar_label: Java +description: Official TurboDocx Java SDK. Builder pattern API with comprehensive error handling for document generation and digital signatures. +keywords: + - turbodocx java + - turbosign java + - maven turbodocx + - gradle turbodocx + - java sdk + - document api java + - esignature java +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Java SDK + +The official TurboDocx SDK for Java applications. Build document generation and digital signature workflows with the Builder pattern, comprehensive error handling, and type-safe APIs. Available on Maven Central as `com.turbodocx:sdk`. + +## Installation + + + + +```xml + + com.turbodocx + sdk + 1.0.0 + +``` + + + + +```kotlin +implementation("com.turbodocx:sdk:1.0.0") +``` + + + + +```groovy +implementation 'com.turbodocx:sdk:1.0.0' +``` + + + + +## Requirements + +- Java 11+ +- OkHttp 4.x (included) +- Gson 2.x (included) + +--- + +## Configuration + +```java +import com.turbodocx.TurboDocxClient; + +public class Main { + public static void main(String[] args) { + // Create client with Builder pattern + TurboDocxClient client = new TurboDocxClient.Builder() + .apiKey(System.getenv("TURBODOCX_API_KEY")) + .orgId(System.getenv("TURBODOCX_ORG_ID")) + .build(); + + // Or with custom base URL + TurboDocxClient client = new TurboDocxClient.Builder() + .apiKey(System.getenv("TURBODOCX_API_KEY")) + .orgId(System.getenv("TURBODOCX_ORG_ID")) + .baseUrl("https://api.turbodocx.com") + .build(); + } +} +``` + +### Environment Variables + +```bash +export TURBODOCX_API_KEY=your_api_key_here +export TURBODOCX_ORG_ID=your_org_id_here +``` + +:::warning API Credentials Required +Both `apiKey` and `orgId` parameters are **required** for all API requests. To get your credentials, follow the **[Get Your Credentials](/docs/SDKs#1-get-your-credentials)** steps from the SDKs main page. +::: + +--- + +## Quick Start + +### Send a Document for Signature + +```java +import com.turbodocx.TurboDocxClient; +import com.turbodocx.models.*; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.util.Arrays; + +public class Main { + public static void main(String[] args) throws Exception { + TurboDocxClient client = new TurboDocxClient.Builder() + .apiKey(System.getenv("TURBODOCX_API_KEY")) + .orgId(System.getenv("TURBODOCX_ORG_ID")) + .build(); + + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + SendSignatureResponse result = client.turboSign().sendSignature( + new SendSignatureRequest.Builder() + .fileLink("https://example.com/contract.pdf") + .documentName("Service Agreement") + .senderName("Acme Corp") + .senderEmail("contracts@acme.com") + .recipients(Arrays.asList( + new Recipient("Alice Smith", "alice@example.com", 1), + new Recipient("Bob Johnson", "bob@example.com", 2) + )) + .fields(Arrays.asList( + // Alice's signature + new Field("signature", 1, 100, 650, 200, 50, "alice@example.com"), + new Field("date", 1, 320, 650, 100, 30, "alice@example.com"), + // Bob's signature + new Field("signature", 1, 100, 720, 200, 50, "bob@example.com"), + new Field("date", 1, 320, 720, 100, 30, "bob@example.com") + )) + .build() + ); + + System.out.println("Result: " + gson.toJson(result)); + } +} +``` + +### Using Template-Based Fields + +```java +// Template-based field using anchor text +Field.TemplateAnchor templateAnchor = new Field.TemplateAnchor( + "{SIGNATURE_ALICE}", // anchor text to find + null, // searchText (alternative to anchor) + "replace", // placement: replace/before/after/above/below + new Field.Size(200, 50), // size + null, // offset + false, // caseSensitive + false // useRegex +); + +// Field with template anchor (no page/x/y coordinates needed) +Field templateField = new Field( + "signature", // type + null, // page (null for template-based) + null, // x (null for template-based) + null, // y (null for template-based) + null, // width (null, using template size) + null, // height (null, using template size) + "alice@example.com", // recipientEmail + null, // defaultValue + null, // isMultiline + null, // isReadonly + null, // required + null, // backgroundColor + templateAnchor // template anchor config +); + +SendSignatureResponse result = client.turboSign().sendSignature( + new SendSignatureRequest.Builder() + .fileLink("https://example.com/contract-with-placeholders.pdf") + .recipients(Arrays.asList( + new Recipient("Alice Smith", "alice@example.com", 1) + )) + .fields(Arrays.asList(templateField)) + .build() +); +``` + +:::info Template Anchors Required +**Important:** The document file must contain the anchor text (e.g., `{SIGNATURE_ALICE}`, `{DATE_ALICE}`) that you reference in your fields. If the anchors don't exist in the document, the API will return an error. +::: + +--- + +## File Input Methods + +The SDK supports multiple ways to provide your document: + +### 1. File Upload (byte[]) + +Upload a document directly from file bytes: + +```java +import java.nio.file.Files; +import java.nio.file.Paths; + +byte[] pdfBytes = Files.readAllBytes(Paths.get("/path/to/document.pdf")); + +SendSignatureResponse result = client.turboSign().sendSignature( + new SendSignatureRequest.Builder() + .file(pdfBytes) + .recipients(Arrays.asList( + new Recipient("John Doe", "john@example.com", 1) + )) + .fields(Arrays.asList( + new Field("signature", 1, 100, 500, 200, 50, "john@example.com") + )) + .build() +); +``` + +### 2. File URL + +Provide a publicly accessible URL to your document: + +```java +SendSignatureResponse result = client.turboSign().sendSignature( + new SendSignatureRequest.Builder() + .fileLink("https://example.com/documents/contract.pdf") + .recipients(Arrays.asList( + new Recipient("John Doe", "john@example.com", 1) + )) + .fields(Arrays.asList( + new Field("signature", 1, 100, 500, 200, 50, "john@example.com") + )) + .build() +); +``` + +:::tip When to use fileLink +Use `fileLink` when your documents are already hosted on cloud storage (S3, Google Cloud Storage, etc.). This is more efficient than downloading and re-uploading files. +::: + +### 3. TurboDocx Deliverable ID + +Use a document generated by TurboDocx document generation: + +```java +SendSignatureResponse result = client.turboSign().sendSignature( + new SendSignatureRequest.Builder() + .deliverableId("deliverable-uuid-from-turbodocx") + .recipients(Arrays.asList( + new Recipient("John Doe", "john@example.com", 1) + )) + .fields(Arrays.asList( + new Field("signature", 1, 100, 500, 200, 50, "john@example.com") + )) + .build() +); +``` + +:::info Integration with TurboDocx +`deliverableId` references documents generated using TurboDocx's document generation API. This creates a seamless workflow: generate → sign. +::: + +### 4. TurboDocx Template ID + +Use a pre-configured TurboDocx template: + +```java +SendSignatureResponse result = client.turboSign().sendSignature( + new SendSignatureRequest.Builder() + .templateId("template-uuid-from-turbodocx") + .recipients(Arrays.asList( + new Recipient("John Doe", "john@example.com", 1) + )) + .fields(Arrays.asList( + new Field("signature", 1, 100, 500, 200, 50, "john@example.com") + )) + .build() +); +``` + +:::info Integration with TurboDocx +`templateId` references pre-configured TurboSign templates created in the TurboDocx dashboard. These templates come with built-in anchors and field positioning, making it easy to reuse signature workflows across multiple documents. +::: + +--- + +## API Reference + +### Configure + +Create a new TurboDocx client using the Builder pattern. + +```java +TurboDocxClient client = new TurboDocxClient.Builder() + .apiKey("your-api-key") // Required + .orgId("your-org-id") // Required + .baseUrl("https://api.turbodocx.com") // Optional + .build(); +``` + +### Prepare for review + +Upload a document for preview without sending emails. + +```java +CreateSignatureReviewLinkResponse result = client.turboSign().createSignatureReviewLink( + new CreateSignatureReviewLinkRequest.Builder() + .fileLink("https://example.com/document.pdf") + .documentName("Contract Draft") + .recipients(Arrays.asList( + new Recipient("John Doe", "john@example.com", 1) + )) + .fields(Arrays.asList( + new Field("signature", 1, 100, 500, 200, 50, "john@example.com") + )) + .build() +); + +System.out.println("Result: " + gson.toJson(result)); +``` + +### Prepare for signing + +Upload a document and immediately send signature requests. + +```java +SendSignatureResponse result = client.turboSign().sendSignature( + new SendSignatureRequest.Builder() + .fileLink("https://example.com/document.pdf") + .documentName("Service Agreement") + .senderName("Your Company") + .senderEmail("sender@company.com") + .recipients(Arrays.asList( + new Recipient("Recipient Name", "recipient@example.com", 1) + )) + .fields(Arrays.asList( + new Field("signature", 1, 100, 500, 200, 50, "recipient@example.com") + )) + .build() +); + +System.out.println("Result: " + gson.toJson(result)); +``` + +### Get status + +Check the status of a document. + +```java +DocumentStatusResponse status = client.turboSign().getStatus("document-uuid"); + +System.out.println("Result: " + gson.toJson(status)); +``` + +### Download document + +Download the completed signed document. + +```java +byte[] pdfData = client.turboSign().download("document-uuid"); + +// Save to file +Files.write(Paths.get("signed-contract.pdf"), pdfData); +``` + +### Get audit trail + +Retrieve the audit trail for a document. + +```java +AuditTrailResponse auditTrail = client.turboSign().getAuditTrail("document-uuid"); + +System.out.println("Result: " + gson.toJson(auditTrail)); +``` + +### Void + +Cancel/void a signature request. + +```java +VoidDocumentResponse result = client.turboSign().voidDocument("document-uuid", "Contract terms changed"); +``` + +### Resend + +Resend signature request emails. + +```java +// Resend to specific recipients +ResendEmailResponse result = client.turboSign().resendEmail( + "document-uuid", + Arrays.asList("recipient-uuid-1", "recipient-uuid-2") +); +``` + +--- + +## Error Handling + +The SDK provides typed exceptions for different error scenarios: + +### Error Types + +| Error Type | Status Code | Description | +| -------------------------------------------- | ----------- | ---------------------------------- | +| `TurboDocxException` | varies | Base exception for all API errors | +| `TurboDocxException.AuthenticationException` | 401 | Invalid or missing API credentials | +| `TurboDocxException.ValidationException` | 400 | Invalid request parameters | +| `TurboDocxException.NotFoundException` | 404 | Document or resource not found | +| `TurboDocxException.RateLimitException` | 429 | Too many requests | +| `TurboDocxException.NetworkException` | - | Network connectivity issues | + +### Error Properties + +| Property | Type | Description | +| ----------------- | -------- | ---------------------------- | +| `getMessage()` | `String` | Human-readable error message | +| `getStatusCode()` | `int` | HTTP status code | +| `getCode()` | `String` | Error code (if available) | + +### Example + +```java +import com.turbodocx.TurboDocxException; + +try { + SendSignatureResponse result = client.turboSign().sendSignature(request); +} catch (TurboDocxException.AuthenticationException e) { + System.err.println("Authentication failed: " + e.getMessage()); + // Check your API key and org ID +} catch (TurboDocxException.ValidationException e) { + System.err.println("Validation error: " + e.getMessage()); + // Check request parameters +} catch (TurboDocxException.NotFoundException e) { + System.err.println("Not found: " + e.getMessage()); + // Document or recipient doesn't exist +} catch (TurboDocxException.RateLimitException e) { + System.err.println("Rate limited: " + e.getMessage()); + // Wait and retry +} catch (TurboDocxException.NetworkException e) { + System.err.println("Network error: " + e.getMessage()); + // Check connectivity +} catch (TurboDocxException e) { + // Base exception for other API errors + System.err.println("API error [" + e.getStatusCode() + "]: " + e.getMessage()); +} +``` + +--- + +## Types + +### Signature Field Types + +The `type` field accepts the following string values: + +| Type | Description | +| -------------- | ---------------- | +| `"signature"` | Signature field | +| `"initials"` | Initials field | +| `"text"` | Text input field | +| `"date"` | Date field | +| `"checkbox"` | Checkbox field | +| `"full_name"` | Full name field | +| `"first_name"` | First name field | +| `"last_name"` | Last name field | +| `"email"` | Email field | +| `"title"` | Title field | +| `"company"` | Company field | + +### Recipient + +| Property | Type | Required | Description | +| -------------- | -------- | -------- | ------------------------------------------------- | +| `name` | `String` | Yes | Recipient's full name | +| `email` | `String` | Yes | Recipient's email address | +| `signingOrder` | `int` | Yes | Order in which recipient should sign (1, 2, 3...) | + +### Field + +| Property | Type | Required | Description | +| ----------------- | ---------------- | -------- | ------------------------------------------- | +| `type` | `String` | Yes | Field type (see table above) | +| `recipientEmail` | `String` | Yes | Email of the recipient who fills this field | +| `page` | `Integer` | No\* | Page number (1-indexed) | +| `x` | `Integer` | No\* | X coordinate in pixels | +| `y` | `Integer` | No\* | Y coordinate in pixels | +| `width` | `Integer` | No* | Field width in pixels | +| `height` | `Integer` | No* | Field height in pixels | +| `defaultValue` | `String` | No | Pre-filled value | +| `isMultiline` | `Boolean` | No | Enable multiline for text fields | +| `isReadonly` | `Boolean` | No | Make field read-only | +| `required` | `Boolean` | No | Make field required | +| `backgroundColor` | `String` | No | Background color | +| `template` | `TemplateAnchor` | No | Template anchor configuration | + +\*Required when not using template anchors + +#### Template Configuration + +When using `template` instead of coordinates: + +| Property | Type | Required | Description | +| --------------- | --------- | -------- | ------------------------------------------------------------------------------------- | +| `anchor` | `String` | Yes | Text to find in document (e.g., `"{SIGNATURE}"`) | | +| `placement` | `String` | Yes | Position relative to anchor: `"replace"`, `"before"`, `"after"`, `"above"`, `"below"` | +| `size` | `Size` | Yes | Size with `width` and `height` | +| `offset` | `Offset` | No | Offset with `x` and `y` | +| `caseSensitive` | `Boolean` | No | Case-sensitive anchor search | +| `useRegex` | `Boolean` | No | Use regex for anchor search | + +### Request Parameters + +Both `CreateSignatureReviewLinkRequest` and `SendSignatureRequest` accept: + +| Property | Type | Required | Description | +| --------------------- | ----------------- | ----------- | ------------------------ | +| `file` | `byte[]` | Conditional | File content as bytes | +| `fileLink` | `String` | Conditional | URL to document | +| `deliverableId` | `String` | Conditional | TurboDocx deliverable ID | +| `templateId` | `String` | Conditional | TurboDocx template ID | +| `recipients` | `List` | Yes | List of recipients | +| `fields` | `List` | Yes | List of fields | +| `documentName` | `String` | No | Document display name | +| `documentDescription` | `String` | No | Document description | +| `senderName` | `String` | No | Sender's name | +| `senderEmail` | `String` | No | Sender's email | +| `ccEmails` | `List` | No | CC email addresses | + +:::info File Source (Conditional) +Exactly one file source is required: `file`, `fileLink`, `deliverableId`, or `templateId`. +::: + +--- + +## Additional Documentation + +For detailed information about advanced configuration and API concepts, see: + +### Core API References + +- **[Request Body Reference](/docs/TurboSign/API%20Signatures#request-body-multipartform-data)** - Complete request body parameters, file sources, and multipart/form-data structure +- **[Recipients Reference](/docs/TurboSign/API%20Signatures#recipients-reference)** - Recipient properties, signing order, metadata, and configuration options +- **[Field Types Reference](/docs/TurboSign/API%20Signatures#field-types-reference)** - All available field types (signature, date, text, checkbox, etc.) with properties and behaviors +- **[Field Positioning Methods](/docs/TurboSign/API%20Signatures#field-positioning-methods)** - Template-based vs coordinate-based positioning, anchor configuration, and best practices + +--- + +## Resources + +- [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/java-sdk) +- [Maven Central](https://search.maven.org/artifact/com.turbodocx/sdk) +- [API Reference](/docs/TurboSign/API-Signatures) +- [Webhook Configuration](/docs/TurboSign/Webhooks) diff --git a/docs/SDKs/javascript.md b/docs/SDKs/javascript.md new file mode 100644 index 0000000..2b6a01c --- /dev/null +++ b/docs/SDKs/javascript.md @@ -0,0 +1,1145 @@ +--- +title: JavaScript / TypeScript SDK +sidebar_position: 2 +sidebar_label: JavaScript / TypeScript +description: Official TurboDocx JavaScript and TypeScript SDK. Full TypeScript support with async/await patterns for document generation and digital signatures. +keywords: + - turbodocx javascript + - turbodocx typescript + - turbosign javascript + - node.js sdk + - typescript sdk + - npm turbodocx + - document api javascript + - esignature javascript +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# JavaScript / TypeScript SDK + +The official TurboDocx SDK for JavaScript and TypeScript applications. Build document generation and digital signature workflows with full TypeScript support, async/await patterns, and comprehensive error handling. Available on npm as `@turbodocx/sdk`. + +## Installation + + + + +```bash +npm install @turbodocx/sdk +``` + + + + +```bash +yarn add @turbodocx/sdk +``` + + + + +```bash +pnpm add @turbodocx/sdk +``` + + + + +## Requirements + +- Node.js 18+ or modern browser +- TypeScript 4.7+ (optional, for type checking) + +--- + +## Configuration + + + + +```javascript +const { TurboSign } = require("@turbodocx/sdk"); + +// Configure globally (recommended for server-side) +TurboSign.configure({ + apiKey: process.env.TURBODOCX_API_KEY, // Required : Your TurboDocx API key + orgId: process.env.TURBODOCX_ORG_ID, // Required: Your organization ID + // Optional: override base URL for testing + // baseUrl: 'https://api.turbodocx.com' +}); +``` + + + + +```typescript +import { TurboSign } from "@turbodocx/sdk"; + +// Configure globally (recommended for server-side) +TurboSign.configure({ + apiKey: process.env.TURBODOCX_API_KEY || "", // Required : Your TurboDocx API key + orgId: process.env.TURBODOCX_ORG_ID || "", // Required: Your organization ID + // Optional: override base URL for testing + // baseUrl: 'https://api.turbodocx.com' +}); +``` + + + + +:::tip Authentication +Authenticate using `apiKey`. API keys are recommended for server-side applications. +::: + +### Environment Variables + +```bash +# .env +TURBODOCX_API_KEY=your_api_key_here +TURBODOCX_ORG_ID=your_org_id_here +``` + +--- + +## Quick Start + +### Send a Document for Signature + + + + +```javascript +const { TurboSign } = require("@turbodocx/sdk"); + +TurboSign.configure({ + apiKey: process.env.TURBODOCX_API_KEY, + orgId: process.env.TURBODOCX_ORG_ID, +}); + +// Send document with coordinate-based fields +const result = await TurboSign.sendSignature({ + fileLink: "https://example.com/contract.pdf", + documentName: "Service Agreement", + senderName: "Acme Corp", + senderEmail: "contracts@acme.com", + recipients: [ + { name: "Alice Smith", email: "alice@example.com", signingOrder: 1 }, + { name: "Bob Johnson", email: "bob@example.com", signingOrder: 2 }, + ], + fields: [ + // Alice's signature + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "alice@example.com", + }, + { + type: "date", + page: 1, + x: 320, + y: 650, + width: 100, + height: 30, + recipientEmail: "alice@example.com", + }, + // Bob's signature + { + type: "signature", + page: 1, + x: 100, + y: 720, + width: 200, + height: 50, + recipientEmail: "bob@example.com", + }, + { + type: "date", + page: 1, + x: 320, + y: 720, + width: 100, + height: 30, + recipientEmail: "bob@example.com", + }, + ], +}); + +console.log(JSON.stringify(result, null, 2)); +``` + + + + +```typescript +import { TurboSign } from "@turbodocx/sdk"; + +TurboSign.configure({ + apiKey: process.env.TURBODOCX_API_KEY || "", + orgId: process.env.TURBODOCX_ORG_ID || "", +}); + +// Send document with coordinate-based fields +const result = await TurboSign.sendSignature({ + fileLink: "https://example.com/contract.pdf", + documentName: "Service Agreement", + senderName: "Acme Corp", + senderEmail: "contracts@acme.com", + recipients: [ + { name: "Alice Smith", email: "alice@example.com", signingOrder: 1 }, + { name: "Bob Johnson", email: "bob@example.com", signingOrder: 2 }, + ], + fields: [ + // Alice's signature + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "alice@example.com", + }, + { + type: "date", + page: 1, + x: 320, + y: 650, + width: 100, + height: 30, + recipientEmail: "alice@example.com", + }, + // Bob's signature + { + type: "signature", + page: 1, + x: 100, + y: 720, + width: 200, + height: 50, + recipientEmail: "bob@example.com", + }, + { + type: "date", + page: 1, + x: 320, + y: 720, + width: 100, + height: 30, + recipientEmail: "bob@example.com", + }, + ], +}); + +console.log(JSON.stringify(result, null, 2)); +``` + + + + +### Using Template-Based Fields + + + + +```javascript +// Use text anchors instead of coordinates +const result = await TurboSign.sendSignature({ + fileLink: "https://example.com/contract-with-placeholders.pdf", + recipients: [ + { name: "Alice Smith", email: "alice@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + recipientEmail: "alice@example.com", + template: { + anchor: "{SIGNATURE_ALICE}", + placement: "replace", + size: { width: 200, height: 50 }, + }, + }, + { + type: "date", + recipientEmail: "alice@example.com", + template: { + anchor: "{DATE_ALICE}", + placement: "replace", + size: { width: 100, height: 30 }, + }, + }, + ], +}); + +console.log(JSON.stringify(result, null, 2)); +``` + + + + +```typescript +// Use text anchors instead of coordinates +const result = await TurboSign.sendSignature({ + fileLink: "https://example.com/contract-with-placeholders.pdf", + recipients: [ + { name: "Alice Smith", email: "alice@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + recipientEmail: "alice@example.com", + template: { + anchor: "{SIGNATURE_ALICE}", + placement: "replace", + size: { width: 200, height: 50 }, + }, + }, + { + type: "date", + recipientEmail: "alice@example.com", + template: { + anchor: "{DATE_ALICE}", + placement: "replace", + size: { width: 100, height: 30 }, + }, + }, + ], +}); + +console.log(JSON.stringify(result, null, 2)); +``` + + + + +:::info Template Anchors Required +**Important:** The document file must contain the anchor text (e.g., `{SIGNATURE_ALICE}`, `{DATE_ALICE}`) that you reference in your fields. If the anchors don't exist in the document, the API will return an error. + +**Alternative:** Use a TurboDocx template with pre-configured anchors: + +```typescript +const result = await TurboSign.sendSignature({ + templateId: "template-uuid-from-turbodocx", // Template already contains anchors + recipients: [ + { name: "Alice Smith", email: "alice@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + recipientEmail: "alice@example.com", + template: { + anchor: "{SIGNATURE_ALICE}", + placement: "replace", + size: { width: 200, height: 50 }, + }, + }, + ], +}); +``` + +::: + +--- + +## File Input Methods + +TurboSign supports four different ways to provide document files: + +### 1. File Upload (Buffer/Blob) + + + + +```javascript +const { readFileSync } = require("fs"); +const { TurboSign } = require("@turbodocx/sdk"); + +const fileBuffer = readFileSync("./contract.pdf"); + +const result = await TurboSign.sendSignature({ + file: fileBuffer, + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); +``` + + + + +```typescript +import { readFileSync } from "fs"; +import { TurboSign } from "@turbodocx/sdk"; + +const fileBuffer = readFileSync("./contract.pdf"); + +const result = await TurboSign.sendSignature({ + file: fileBuffer, + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); +``` + + + + +### 2. File URL (fileLink) + + + + +```javascript +const result = await TurboSign.sendSignature({ + fileLink: "https://storage.example.com/contracts/agreement.pdf", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); +``` + + + + +```typescript +const result = await TurboSign.sendSignature({ + fileLink: "https://storage.example.com/contracts/agreement.pdf", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); +``` + + + + +:::tip When to use fileLink +Use `fileLink` when your documents are already hosted on cloud storage (S3, Google Cloud Storage, etc.). This is more efficient than downloading and re-uploading files. +::: + +### 3. TurboDocx Deliverable ID + + + + +```javascript +// Use a previously generated TurboDocx document +const result = await TurboSign.sendSignature({ + deliverableId: "deliverable-uuid-from-turbodocx", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); +``` + + + + +```typescript +// Use a previously generated TurboDocx document +const result = await TurboSign.sendSignature({ + deliverableId: "deliverable-uuid-from-turbodocx", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); +``` + + + + +:::info Integration with TurboDocx +`deliverableId` references documents generated using TurboDocx's document generation API. This creates a seamless workflow: generate → sign. +::: + +### 4. TurboDocx Template ID + + + + +```javascript +// Use a pre-configured TurboSign template +const result = await TurboSign.sendSignature({ + templateId: "template-uuid-from-turbodocx", // Template already contains anchors + recipients: [ + { name: "Alice Smith", email: "alice@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + recipientEmail: "alice@example.com", + template: { + anchor: "{SIGNATURE_ALICE}", + placement: "replace", + size: { width: 200, height: 50 }, + }, + }, + ], +}); +``` + + + + +```typescript +// Use a pre-configured TurboSign template +const result = await TurboSign.sendSignature({ + templateId: "template-uuid-from-turbodocx", // Template already contains anchors + recipients: [ + { name: "Alice Smith", email: "alice@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + recipientEmail: "alice@example.com", + template: { + anchor: "{SIGNATURE_ALICE}", + placement: "replace", + size: { width: 200, height: 50 }, + }, + }, + ], +}); +``` + + + + +:::info Integration with TurboDocx +`templateId` references pre-configured TurboSign templates created in the TurboDocx dashboard. These templates come with built-in anchors and field positioning, making it easy to reuse signature workflows across multiple documents. +::: + +--- + +## API Reference + +### Configure + +Configure the SDK with your API credentials and organization settings. + +```typescript +TurboSign.configure({ + apiKey: string; // Required : Your TurboDocx API key + orgId: string; // Required: Your organization ID + baseUrl?: string; // Optional: API base URL (default: 'https://api.turbodocx.com') +}); +``` + +**Example:** + + + + +```javascript +const { TurboSign } = require("@turbodocx/sdk"); + +TurboSign.configure({ + apiKey: process.env.TURBODOCX_API_KEY, + orgId: process.env.TURBODOCX_ORG_ID, + // Optional: override for testing + // baseUrl: 'https://api.turbodocx.com' +}); +``` + + + + +```typescript +import { TurboSign } from "@turbodocx/sdk"; + +TurboSign.configure({ + apiKey: process.env.TURBODOCX_API_KEY || "", + orgId: process.env.TURBODOCX_ORG_ID || "", + // Optional: override for testing + // baseUrl: 'https://api.turbodocx.com' +}); +``` + + + + +:::warning API Credentials Required +Both `apiKey` and `orgId` parameters are **required** for all API requests. To get your credentials, follow the **[Get Your Credentials](/docs/SDKs#1-get-your-credentials)** steps from the SDKs main page. +::: + +### Prepare for review + +Upload a document for preview without sending signature request emails. + + + + +```javascript +const { documentId, previewUrl } = await TurboSign.createSignatureReviewLink({ + fileLink: "https://example.com/document.pdf", + documentName: "Contract Draft", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 500, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); +``` + + + + +```typescript +const { documentId, previewUrl } = await TurboSign.createSignatureReviewLink({ + fileLink: "https://example.com/document.pdf", + documentName: "Contract Draft", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 500, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], +}); +``` + + + + +### Prepare for signing + +Upload a document and immediately send signature requests to all recipients. + + + + +```javascript +const { documentId } = await TurboSign.sendSignature({ + fileLink: "https://example.com/document.pdf", + documentName: "Service Agreement", + senderName: "Your Company", + senderEmail: "sender@company.com", + recipients: [ + { name: "Recipient Name", email: "recipient@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 500, + width: 200, + height: 50, + recipientEmail: "recipient@example.com", + }, + ], +}); +``` + + + + +```typescript +const { documentId } = await TurboSign.sendSignature({ + fileLink: "https://example.com/document.pdf", + documentName: "Service Agreement", + senderName: "Your Company", + senderEmail: "sender@company.com", + recipients: [ + { name: "Recipient Name", email: "recipient@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 500, + width: 200, + height: 50, + recipientEmail: "recipient@example.com", + }, + ], +}); +``` + + + + +### Get status + +Retrieve the current status of a document. + + + + +```javascript +const result = await TurboSign.getStatus("document-uuid"); + +console.log(JSON.stringify(result, null, 2)); +``` + + + + +```typescript +const result = await TurboSign.getStatus("document-uuid"); + +console.log(JSON.stringify(result, null, 2)); +``` + + + + +### Download document + +Download the completed signed document as a PDF Blob. + + + + +```javascript +const result = await TurboSign.download("document-uuid"); + +// Node.js: Save to file +const { writeFileSync } = require("fs"); +const buffer = Buffer.from(await result.arrayBuffer()); +writeFileSync("signed-contract.pdf", buffer); +``` + + + + +```typescript +const result = await TurboSign.download("document-uuid"); + +// Node.js: Save to file +import { writeFileSync } from "fs"; +const buffer = Buffer.from(await result.arrayBuffer()); +writeFileSync("signed-contract.pdf", buffer); +``` + + + + +### Void + +Cancel/void a signature request. + + + + +```javascript +await TurboSign.void("document-uuid", "Contract terms changed"); +``` + + + + +```typescript +await TurboSign.void("document-uuid", "Contract terms changed"); +``` + + + + +### Resend + +Resend signature request emails to specific recipients. + + + + +```javascript +// Resend to specific recipients +await TurboSign.resend("document-uuid", [ + "recipient-uuid-1", + "recipient-uuid-2", +]); +``` + + + + +```typescript +// Resend to specific recipients +await TurboSign.resend("document-uuid", [ + "recipient-uuid-1", + "recipient-uuid-2", +]); +``` + + + + +### Get audit trail + +Retrieve the complete audit trail for a document, including all events and actions. + + + + +```javascript +const result = await TurboSign.getAuditTrail("document-uuid"); + +console.log(JSON.stringify(result, null, 2)); +``` + + + + +```typescript +const result = await TurboSign.getAuditTrail("document-uuid"); + +console.log(JSON.stringify(result, null, 2)); +``` + + + + +--- + +## Error Handling + +The SDK provides typed error classes for different failure scenarios. All errors extend the base `TurboDocxError` class. + +### Error Classes + +| Error Class | Status Code | Code | Description | +|-------------|-------------|------|-------------| +| `TurboDocxError` | varies | varies | Base error class for all SDK errors | +| `AuthenticationError` | 401 | `AUTHENTICATION_ERROR` | Invalid or missing API credentials | +| `ValidationError` | 400 | `VALIDATION_ERROR` | Invalid request parameters | +| `NotFoundError` | 404 | `NOT_FOUND` | Document or resource not found | +| `RateLimitError` | 429 | `RATE_LIMIT_EXCEEDED` | Too many requests | +| `NetworkError` | - | `NETWORK_ERROR` | Network connectivity issues | + +### Handling Errors + + + + +```javascript +const { + TurboSign, + TurboDocxError, + AuthenticationError, + ValidationError, + NotFoundError, + RateLimitError, + NetworkError, +} = require("@turbodocx/sdk"); + +try { + const result = await TurboSign.sendSignature({ + fileLink: "https://example.com/contract.pdf", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], + }); +} catch (error) { + if (error instanceof AuthenticationError) { + console.error("Authentication failed:", error.message); + // Check your API key and org ID + } else if (error instanceof ValidationError) { + console.error("Validation error:", error.message); + // Check request parameters + } else if (error instanceof NotFoundError) { + console.error("Resource not found:", error.message); + // Document or recipient doesn't exist + } else if (error instanceof RateLimitError) { + console.error("Rate limited:", error.message); + // Wait and retry + } else if (error instanceof NetworkError) { + console.error("Network error:", error.message); + // Check connectivity + } else if (error instanceof TurboDocxError) { + console.error("SDK error:", error.message, error.statusCode, error.code); + } +} +``` + + + + +```typescript +import { + TurboSign, + TurboDocxError, + AuthenticationError, + ValidationError, + NotFoundError, + RateLimitError, + NetworkError, +} from "@turbodocx/sdk"; + +try { + const result = await TurboSign.sendSignature({ + fileLink: "https://example.com/contract.pdf", + recipients: [ + { name: "John Doe", email: "john@example.com", signingOrder: 1 }, + ], + fields: [ + { + type: "signature", + page: 1, + x: 100, + y: 650, + width: 200, + height: 50, + recipientEmail: "john@example.com", + }, + ], + }); +} catch (error) { + if (error instanceof AuthenticationError) { + console.error("Authentication failed:", error.message); + // Check your API key and org ID + } else if (error instanceof ValidationError) { + console.error("Validation error:", error.message); + // Check request parameters + } else if (error instanceof NotFoundError) { + console.error("Resource not found:", error.message); + // Document or recipient doesn't exist + } else if (error instanceof RateLimitError) { + console.error("Rate limited:", error.message); + // Wait and retry + } else if (error instanceof NetworkError) { + console.error("Network error:", error.message); + // Check connectivity + } else if (error instanceof TurboDocxError) { + console.error("SDK error:", error.message, error.statusCode, error.code); + } +} +``` + + + + +### Error Properties + +All errors include these properties: + +| Property | Type | Description | +|----------|------|-------------| +| `message` | `string` | Human-readable error description | +| `statusCode` | `number \| undefined` | HTTP status code (if applicable) | +| `code` | `string \| undefined` | Machine-readable error code | + +--- + +## TypeScript Types + +The SDK exports TypeScript types for full type safety. Import them directly from the package. + +### Importing Types + +```typescript +import type { + // Field types + SignatureFieldType, + N8nField, + N8nRecipient, + // Request types + CreateSignatureReviewLinkRequest, + SendSignatureRequest, +} from "@turbodocx/sdk"; +``` + +### SignatureFieldType + +Union type for all available field types: + +```typescript +type SignatureFieldType = + | "signature" + | "initial" + | "date" + | "text" + | "full_name" + | "title" + | "company" + | "first_name" + | "last_name" + | "email" + | "checkbox"; +``` + +### N8nRecipient + +Recipient configuration for signature requests: + +| Property | Type | Required | Description | +|----------|------|----------|-------------| +| `name` | `string` | Yes | Recipient's full name | +| `email` | `string` | Yes | Recipient's email address | +| `signingOrder` | `number` | Yes | Signing order (1-indexed) | + +### N8nField + +Field configuration supporting both coordinate-based and template-based positioning: + +| Property | Type | Required | Description | +|----------|------|----------|-------------| +| `type` | `SignatureFieldType` | Yes | Field type | +| `recipientEmail` | `string` | Yes | Which recipient fills this field | +| `page` | `number` | No\* | Page number (1-indexed) | +| `x` | `number` | No\* | X coordinate in pixels | +| `y` | `number` | No\* | Y coordinate in pixels | +| `width` | `number` | No* | Field width in pixels | +| `height` | `number` | No* | Field height in pixels | +| `defaultValue` | `string` | No | Default value (for checkbox: `"true"` or `"false"`) | +| `isMultiline` | `boolean` | No | Enable multiline text | +| `isReadonly` | `boolean` | No | Make field read-only (pre-filled) | +| `required` | `boolean` | No | Whether field is required | +| `backgroundColor` | `string` | No | Background color (hex, rgb, or named) | +| `template` | `object` | No | Template anchor configuration | + +\*Required when not using template anchors + +**Template Configuration:** + +| Property | Type | Required | Description | +|----------|------|----------|-------------| +| `anchor` | `string` | Yes | Text anchor pattern like `{TagName}` | +| `placement` | `string` | Yes | `"replace"` \| `"before"` \| `"after"` \| `"above"` \| `"below"` | +| `size` | `object` | Yes | `{ width: number; height: number }` | +| `offset` | `object` | No | `{ x: number; y: number }` | +| `caseSensitive` | `boolean` | No | Case sensitive search (default: false) | +| `useRegex` | `boolean` | No | Use regex for anchor/searchText (default: false) | + +### CreateSignatureReviewLinkRequest / SendSignatureRequest + +Request configuration for `createSignatureReviewLink` and `sendSignature` methods: + +| Property | Type | Required | Description | +|----------|------|----------|-------------| +| `file` | `Buffer` | Conditional | PDF file as Buffer | +| `fileLink` | `string` | Conditional | URL to document file | +| `deliverableId` | `string` | Conditional | TurboDocx deliverable ID | +| `templateId` | `string` | Conditional | TurboDocx template ID | +| `recipients` | `N8nRecipient[]` | Yes | Recipients who will sign | +| `fields` | `N8nField[]` | Yes | Signature fields configuration | +| `documentName` | `string` | No | Document name | +| `documentDescription` | `string` | No | Document description | +| `senderName` | `string` | No | Sender name | +| `senderEmail` | `string` | No | Sender email | +| `ccEmails` | `string[]` | No | Array of CC email addresses | + +:::info File Source (Conditional) +Exactly one file source is required: `file`, `fileLink`, `deliverableId`, or `templateId`. +::: + +--- + +## Additional Documentation + +For detailed information about advanced configuration and API concepts, see: + +### Core API References + +- **[Request Body Reference](/docs/TurboSign/API%20Signatures#request-body-multipartform-data)** - Complete request body parameters, file sources, and multipart/form-data structure +- **[Recipients Reference](/docs/TurboSign/API%20Signatures#recipients-reference)** - Recipient properties, signing order, metadata, and configuration options +- **[Field Types Reference](/docs/TurboSign/API%20Signatures#field-types-reference)** - All available field types (signature, date, text, checkbox, etc.) with properties and behaviors +- **[Field Positioning Methods](/docs/TurboSign/API%20Signatures#field-positioning-methods)** - Template-based vs coordinate-based positioning, anchor configuration, and best practices + +--- + +## Resources + +- [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/js-sdk) +- [npm Package](https://www.npmjs.com/package/@turbodocx/sdk) +- [API Reference](/docs/TurboSign/API%20Signatures) +- [Webhook Configuration](/docs/TurboSign/Webhooks) diff --git a/docs/SDKs/python.md b/docs/SDKs/python.md new file mode 100644 index 0000000..f97ef01 --- /dev/null +++ b/docs/SDKs/python.md @@ -0,0 +1,589 @@ +--- +title: Python SDK +sidebar_position: 3 +sidebar_label: Python +description: Official TurboDocx Python SDK. Async-first design with sync wrappers for document generation and digital signatures. +keywords: + - turbodocx python + - turbosign python + - python sdk + - pip turbodocx + - asyncio sdk + - fastapi turbodocx + - django turbodocx + - document api python +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Python SDK + +The official TurboDocx SDK for Python applications. Build document generation and digital signature workflows with async/await patterns and comprehensive error handling. Available on PyPI as `turbodocx-sdk`. + +## Installation + + + + +```bash +pip install turbodocx-sdk +``` + + + + +```bash +poetry add turbodocx-sdk +``` + + + + +```bash +pipenv install turbodocx-sdk +``` + + + + +## Requirements + +- Python 3.8+ +- `httpx` (installed automatically) +- `pydantic` (installed automatically) + +--- + +## Configuration + +```python +from turbodocx_sdk import TurboSign +import os + +# Configure globally (recommended) +TurboSign.configure( + api_key=os.environ["TURBODOCX_API_KEY"], # Required: Your TurboDocx API key + org_id=os.environ["TURBODOCX_ORG_ID"], # Required: Your organization ID + # base_url="https://api.turbodocx.com" # Optional: Override base URL +) +``` + +:::tip Authentication +Authenticate using `api_key`. API keys are recommended for server-side applications. +::: + +### Environment Variables + +```bash +# .env +TURBODOCX_API_KEY=your_api_key_here +TURBODOCX_ORG_ID=your_org_id_here +``` + +:::warning API Credentials Required +Both `api_key` and `org_id` parameters are **required** for all API requests. To get your credentials, follow the **[Get Your Credentials](/docs/SDKs#1-get-your-credentials)** steps from the SDKs main page. +::: + +--- + +## Quick Start + +### Send a Document for Signature + +```python +import asyncio +from turbodocx_sdk import TurboSign +import os + +TurboSign.configure( + api_key=os.environ["TURBODOCX_API_KEY"], + org_id=os.environ["TURBODOCX_ORG_ID"] +) + +async def send_contract(): + result = await TurboSign.send_signature( + recipients=[ + {"name": "Alice Smith", "email": "alice@example.com", "signingOrder": 1}, + {"name": "Bob Johnson", "email": "bob@example.com", "signingOrder": 2} + ], + fields=[ + # Alice's signature + {"type": "signature", "page": 1, "x": 100, "y": 650, "width": 200, "height": 50, "recipientEmail": "alice@example.com"}, + {"type": "date", "page": 1, "x": 320, "y": 650, "width": 100, "height": 30, "recipientEmail": "alice@example.com"}, + # Bob's signature + {"type": "signature", "page": 1, "x": 100, "y": 720, "width": 200, "height": 50, "recipientEmail": "bob@example.com"}, + {"type": "date", "page": 1, "x": 320, "y": 720, "width": 100, "height": 30, "recipientEmail": "bob@example.com"} + ], + file_link="https://example.com/contract.pdf", + document_name="Service Agreement", + sender_name="Acme Corp", + sender_email="contracts@acme.com", + ) + + print("Result:", json.dumps(result, indent=2)) + +asyncio.run(send_contract()) +``` + +### Using Template-Based Fields + +```python +result = await TurboSign.send_signature( + recipients=[{"name": "Alice Smith", "email": "alice@example.com", "signingOrder": 1}], + fields=[ + { + "type": "signature", + "recipientEmail": "alice@example.com", + "template": { + "anchor": "{SIGNATURE_ALICE}", + "placement": "replace", + "size": {"width": 200, "height": 50}, + }, + }, + { + "type": "date", + "recipientEmail": "alice@example.com", + "template": { + "anchor": "{DATE_ALICE}", + "placement": "replace", + "size": {"width": 100, "height": 30}, + }, + }, + ], + file_link="https://example.com/contract-with-placeholders.pdf", +) + +print("Result:", json.dumps(result, indent=2)) +``` + +:::info Template Anchors Required +**Important:** The document file must contain the anchor text (e.g., `{SIGNATURE_ALICE}`, `{DATE_ALICE}`) that you reference in your fields. If the anchors don't exist in the document, the API will return an error. +::: + +--- + +## File Input Methods + +TurboSign supports four different ways to provide document files: + +### 1. File Upload (bytes) + +```python +with open("./contract.pdf", "rb") as f: + pdf_buffer = f.read() + +result = await TurboSign.send_signature( + file=pdf_buffer, + recipients=[ + {"name": "John Doe", "email": "john@example.com", "signingOrder": 1}, + ], + fields=[ + { + "type": "signature", + "page": 1, + "x": 100, + "y": 650, + "width": 200, + "height": 50, + "recipientEmail": "john@example.com", + }, + ], +) +``` + +### 2. File URL (file_link) + +```python +result = await TurboSign.send_signature( + file_link="https://storage.example.com/contracts/agreement.pdf", + recipients=[ + {"name": "John Doe", "email": "john@example.com", "signingOrder": 1}, + ], + fields=[ + { + "type": "signature", + "page": 1, + "x": 100, + "y": 650, + "width": 200, + "height": 50, + "recipientEmail": "john@example.com", + }, + ], +) +``` + +:::tip When to use file_link +Use `file_link` when your documents are already hosted on cloud storage (S3, Google Cloud Storage, etc.). This is more efficient than downloading and re-uploading files. +::: + +### 3. TurboDocx Deliverable ID + +```python +# Use a previously generated TurboDocx document +result = await TurboSign.send_signature( + deliverable_id="deliverable-uuid-from-turbodocx", + recipients=[ + {"name": "John Doe", "email": "john@example.com", "signingOrder": 1}, + ], + fields=[ + { + "type": "signature", + "page": 1, + "x": 100, + "y": 650, + "width": 200, + "height": 50, + "recipientEmail": "john@example.com", + }, + ], +) +``` + +:::info Integration with TurboDocx +`deliverable_id` references documents generated using TurboDocx's document generation API. This creates a seamless workflow: generate → sign. +::: + +### 4. TurboDocx Template ID + +```python +# Use a pre-configured TurboSign template +result = await TurboSign.send_signature( + template_id="template-uuid-from-turbodocx", # Template already contains anchors + recipients=[ + {"name": "Alice Smith", "email": "alice@example.com", "signingOrder": 1}, + ], + fields=[ + { + "type": "signature", + "recipientEmail": "alice@example.com", + "template": { + "anchor": "{SIGNATURE_ALICE}", + "placement": "replace", + "size": {"width": 200, "height": 50}, + }, + }, + ], +) +``` + +:::info Integration with TurboDocx +`template_id` references pre-configured TurboSign templates created in the TurboDocx dashboard. These templates come with built-in anchors and field positioning, making it easy to reuse signature workflows across multiple documents. +::: + +--- + +## API Reference + +### Configure + +Configure the SDK with your API credentials and organization settings. + +```python +TurboSign.configure( + api_key: str, # Required: Your TurboDocx API key + org_id: str, # Required: Your organization ID + base_url: str = "https://api.turbodocx.com" # Optional: API base URL +) +``` + +### Prepare for review + +Upload a document for preview without sending signature request emails. + +```python +result = await TurboSign.create_signature_review_link( + recipients=[{"name": "John Doe", "email": "john@example.com", "signingOrder": 1}], + fields=[{"type": "signature", "page": 1, "x": 100, "y": 500, "width": 200, "height": 50, "recipientEmail": "john@example.com"}], + file_link="https://example.com/document.pdf", + document_name="Contract Draft", +) + +print(result["documentId"]) +print(result["previewUrl"]) +``` + +### Prepare for signing + +Upload a document and immediately send signature requests to all recipients. + +```python +result = await TurboSign.send_signature( + recipients=[{"name": "Recipient Name", "email": "recipient@example.com", "signingOrder": 1}], + fields=[{"type": "signature", "page": 1, "x": 100, "y": 500, "width": 200, "height": 50, "recipientEmail": "recipient@example.com"}], + file_link="https://example.com/document.pdf", + document_name="Service Agreement", + sender_name="Your Company", + sender_email="sender@company.com", +) + +print(result["documentId"]) +``` + +### Get status + +Retrieve the current status of a document. + +```python +result = await TurboSign.get_status("document-uuid") + +print("Result:", json.dumps(result, indent=2)) +``` + +### Download document + +Download the completed signed document as PDF bytes. + +```python +pdf_bytes = await TurboSign.download("document-uuid") + +# Save to file +with open("signed-contract.pdf", "wb") as f: + f.write(pdf_bytes) +``` + +### Void + +Cancel/void a signature request. + +```python +result = await TurboSign.void_document("document-uuid", reason="Contract terms changed") +``` + +### Resend + +Resend signature request emails to specific recipients. + +```python +result = await TurboSign.resend_email("document-uuid", recipient_ids=["recipient-uuid-1", "recipient-uuid-2"]) +``` + +### Get audit trail + +Retrieve the complete audit trail for a document, including all events and actions. + +```python +result = await TurboSign.get_audit_trail("document-uuid") + +print("Result:", json.dumps(result, indent=2)) +``` + +--- + +## Error Handling + +The SDK provides typed error classes for different failure scenarios. All errors extend the base `TurboDocxError` class. + +### Error Classes + +| Error Class | Status Code | Description | +| --------------------- | ----------- | ----------------------------------- | +| `TurboDocxError` | varies | Base error class for all SDK errors | +| `AuthenticationError` | 401 | Invalid or missing API credentials | +| `ValidationError` | 400 | Invalid request parameters | +| `NotFoundError` | 404 | Document or resource not found | +| `RateLimitError` | 429 | Too many requests | +| `NetworkError` | - | Network connectivity issues | + +### Handling Errors + +```python +from turbodocx_sdk import ( + TurboSign, + TurboDocxError, + AuthenticationError, + ValidationError, + NotFoundError, + RateLimitError, + NetworkError, +) + +try: + result = await TurboSign.send_signature( + recipients=[{"name": "John Doe", "email": "john@example.com", "signingOrder": 1}], + fields=[{ + "type": "signature", + "page": 1, + "x": 100, + "y": 650, + "width": 200, + "height": 50, + "recipientEmail": "john@example.com", + }], + file_link="https://example.com/contract.pdf", + ) +except AuthenticationError as e: + print(f"Authentication failed: {e}") + # Check your API key and org ID +except ValidationError as e: + print(f"Validation error: {e}") + # Check request parameters +except NotFoundError as e: + print(f"Resource not found: {e}") + # Document or recipient doesn't exist +except RateLimitError as e: + print(f"Rate limited: {e}") + # Wait and retry +except NetworkError as e: + print(f"Network error: {e}") + # Check connectivity +except TurboDocxError as e: + print(f"SDK error: {e}, status_code={e.status_code}, code={e.code}") +``` + +### Error Properties + +All errors include these properties: + +| Property | Type | Description | +| ------------- | ------------- | --------------------------------------------------- | +| `message` | `str` | Human-readable error description (via `str(error)`) | +| `status_code` | `int \| None` | HTTP status code (if applicable) | +| `code` | `str \| None` | Machine-readable error code | + +--- + +## Python Types + +The SDK uses Python type hints with `Dict[str, Any]` for flexible JSON-like structures. + +### Importing Types + +```python +from typing import Dict, List, Any, Optional +``` + +### SignatureFieldType + +String literal values for field types: + +```python +# Available field type values +field_types = [ + "signature", + "initial", + "date", + "text", + "full_name", + "title", + "company", + "first_name", + "last_name", + "email", + "checkbox", +] +``` + +### Recipient + +Recipient configuration for signature requests: + +  + +| Property | Type | Required | Description | +| -------------- | ----- | -------- | ------------------------- | +| `name` | `str` | Yes | Recipient's full name | +| `email` | `str` | Yes | Recipient's email address | +| `signingOrder` | `int` | Yes | Signing order (1-indexed) | + +```python +recipient: Dict[str, Any] = { + "name": "John Doe", + "email": "john@example.com", + "signingOrder": 1 +} +``` + +### Field + +Field configuration supporting both coordinate-based and template-based positioning: + +  + +| Property | Type | Required | Description | +| ----------------- | ------ | -------- | --------------------------------------------------- | +| `type` | `str` | Yes | Field type (see SignatureFieldType) | +| `recipientEmail` | `str` | Yes | Which recipient fills this field | +| `page` | `int` | No\* | Page number (1-indexed) | +| `x` | `int` | No\* | X coordinate in pixels | +| `y` | `int` | No\* | Y coordinate in pixels | +| `width` | `int` | No* | Field width in pixels | +| `height` | `int` | No* | Field height in pixels | +| `defaultValue` | `str` | No | Default value (for checkbox: `"true"` or `"false"`) | +| `isMultiline` | `bool` | No | Enable multiline text | +| `isReadonly` | `bool` | No | Make field read-only (pre-filled) | +| `required` | `bool` | No | Whether field is required | +| `backgroundColor` | `str` | No | Background color (hex, rgb, or named) | +| `template` | `Dict` | No | Template anchor configuration | + +\*Required when not using template anchors + +**Template Configuration:** + +| Property | Type | Required | Description | +| --------------- | ------ | -------- | ---------------------------------------------------------------- | +| `anchor` | `str` | Yes | Text anchor pattern like `{TagName}` | +| `placement` | `str` | Yes | `"replace"` \| `"before"` \| `"after"` \| `"above"` \| `"below"` | +| `size` | `Dict` | Yes | `{ "width": int, "height": int }` | +| `offset` | `Dict` | No | `{ "x": int, "y": int }` | +| `caseSensitive` | `bool` | No | Case sensitive search (default: False) | +| `useRegex` | `bool` | No | Use regex for anchor/searchText (default: False) | + +```python +field: Dict[str, Any] = { + "type": "signature", + "page": 1, + "x": 100, + "y": 500, + "width": 200, + "height": 50, + "recipientEmail": "john@example.com" +} +``` + +### Request Parameters + +Request configuration for `create_signature_review_link` and `send_signature` methods: + +  + +| Parameter | Type | Required | Description | +| ---------------------- | ------------ | ----------- | ------------------------------ | +| `recipients` | `List[Dict]` | Yes | Recipients who will sign | +| `fields` | `List[Dict]` | Yes | Signature fields configuration | +| `file` | `bytes` | Conditional | PDF file content as bytes | +| `file_link` | `str` | Conditional | URL to document file | +| `deliverable_id` | `str` | Conditional | TurboDocx deliverable ID | +| `template_id` | `str` | Conditional | TurboDocx template ID | +| `document_name` | `str` | No | Document name | +| `document_description` | `str` | No | Document description | +| `sender_name` | `str` | No | Sender name | +| `sender_email` | `str` | No | Sender email | +| `cc_emails` | `List[str]` | No | Array of CC email addresses | + +:::info File Source (Conditional) +Exactly one file source is required: `file`, `file_link`, `deliverable_id`, or `template_id`. +::: + +--- + +## Additional Documentation + +For detailed information about advanced configuration and API concepts, see: + +### Core API References + +- **[Request Body Reference](/docs/TurboSign/API%20Signatures#request-body-multipartform-data)** - Complete request body parameters, file sources, and multipart/form-data structure +- **[Recipients Reference](/docs/TurboSign/API%20Signatures#recipients-reference)** - Recipient properties, signing order, metadata, and configuration options +- **[Field Types Reference](/docs/TurboSign/API%20Signatures#field-types-reference)** - All available field types (signature, date, text, checkbox, etc.) with properties and behaviors +- **[Field Positioning Methods](/docs/TurboSign/API%20Signatures#field-positioning-methods)** - Template-based vs coordinate-based positioning, anchor configuration, and best practices + +--- + +## Resources + +- [GitHub Repository](https://github.com/TurboDocx/SDK/tree/main/packages/py-sdk) +- [PyPI Package](https://pypi.org/project/turbodocx-sdk/) +- [API Reference](/docs/TurboSign/API%20Signatures) +- [Webhook Configuration](/docs/TurboSign/Webhooks) diff --git a/docs/TurboSign/API Signatures.md b/docs/TurboSign/API Signatures.md index b73de02..454eb63 100644 --- a/docs/TurboSign/API Signatures.md +++ b/docs/TurboSign/API Signatures.md @@ -66,6 +66,12 @@ TurboSign offers two single-step endpoints to fit different workflows: - **Real-time Status Updates**: Track document status throughout the signing process - **Webhook Integration**: Receive notifications when signing is complete +:::tip Prefer using an SDK? +We offer official SDKs that handle authentication, error handling, and type safety for you. + +[View all SDKs →](/docs/SDKs) +::: + ## TLDR; Complete Working Example 🚀 Don't want to read all the details? Here's what you need to know: @@ -1004,7 +1010,7 @@ Now that you've integrated the single-step signing flow, the next step is settin ### Related Documentation -- [TurboSign Setup Guide](/docs/TurboSign/Setting-up-TurboSign) +- [TurboSign Setup Guide](/docs/TurboSign/Setting%20up%20TurboSign) - [Webhook Configuration](/docs/TurboSign/Webhooks) - [API Authentication](/docs/API/turbodocx-api-documentation) - [Integration Examples](/docs/Integrations) diff --git a/docs/TurboSign/Webhooks.md b/docs/TurboSign/Webhooks.md index ff46520..f1101ea 100644 --- a/docs/TurboSign/Webhooks.md +++ b/docs/TurboSign/Webhooks.md @@ -210,12 +210,155 @@ Each webhook request includes these headers: ### Try it Now - +### SDK Verification Examples + +Our SDKs include built-in webhook verification. Here are examples for each language: + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +```typescript +import { verifyWebhookSignature } from '@turbodocx/sdk'; +import express from 'express'; + +const app = express(); + +app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => { + const isValid = verifyWebhookSignature({ + signature: req.headers['x-turbodocx-signature'], + timestamp: req.headers['x-turbodocx-timestamp'], + body: req.body, + secret: process.env.TURBODOCX_WEBHOOK_SECRET + }); + + if (!isValid) { + return res.status(401).json({ error: 'Invalid signature' }); + } + + const event = JSON.parse(req.body.toString()); + // Process event... + res.status(200).json({ received: true }); +}); +``` + + + + +```python +from turbodocx import verify_webhook_signature +from fastapi import FastAPI, Request, HTTPException + +app = FastAPI() + +@app.post("/webhook") +async def handle_webhook(request: Request): + body = await request.body() + + is_valid = verify_webhook_signature( + signature=request.headers.get("x-turbodocx-signature"), + timestamp=request.headers.get("x-turbodocx-timestamp"), + body=body, + secret=os.environ["TURBODOCX_WEBHOOK_SECRET"] + ) + + if not is_valid: + raise HTTPException(status_code=401, detail="Invalid signature") + + event = json.loads(body) + # Process event... + return {"received": True} +``` + + + + +```go +func webhookHandler(w http.ResponseWriter, r *http.Request) { + body, _ := io.ReadAll(r.Body) + + isValid := sdk.VerifyWebhookSignature( + r.Header.Get("X-TurboDocx-Signature"), + r.Header.Get("X-TurboDocx-Timestamp"), + body, + os.Getenv("TURBODOCX_WEBHOOK_SECRET"), + ) + + if !isValid { + http.Error(w, "Invalid signature", http.StatusUnauthorized) + return + } + + var event sdk.WebhookEvent + json.Unmarshal(body, &event) + // Process event... + w.WriteHeader(http.StatusOK) +} +``` + + + + +```csharp +[HttpPost] +public async Task HandleWebhook() +{ + using var reader = new StreamReader(Request.Body); + var body = await reader.ReadToEndAsync(); + + var isValid = WebhookVerifier.VerifySignature( + Request.Headers["X-TurboDocx-Signature"], + Request.Headers["X-TurboDocx-Timestamp"], + body, + _configuration["TurboDocx:WebhookSecret"] + ); + + if (!isValid) + return Unauthorized("Invalid signature"); + + var webhookEvent = JsonSerializer.Deserialize(body); + // Process event... + return Ok(new { Received = true }); +} +``` + + + + +```ruby +def turbodocx_webhook + body = request.raw_post + + is_valid = TurboDocx::WebhookVerifier.verify( + signature: request.headers['X-TurboDocx-Signature'], + timestamp: request.headers['X-TurboDocx-Timestamp'], + body: body, + secret: ENV['TURBODOCX_WEBHOOK_SECRET'] + ) + + unless is_valid + return render json: { error: 'Invalid signature' }, status: :unauthorized + end + + event = JSON.parse(body) + # Process event... + render json: { received: true } +end +``` + + + + +[View full SDK documentation →](/docs/SDKs) + ### Security Best Practices 1. **Always verify signatures**: Never process webhooks without verifying the signature @@ -390,6 +533,6 @@ If you encounter issues not covered here: ## Next Steps -- [Learn about TurboSign](/docs/TurboSign/Setting-up-TurboSign) +- [Learn about TurboSign](/docs/TurboSign/Setting%20up%20TurboSign) - [Explore API Documentation](/docs/API/turbodocx-api-documentation) - [View Integration Guides](/docs/Integrations) diff --git a/sidebars.js b/sidebars.js index 02fe794..b8de214 100644 --- a/sidebars.js +++ b/sidebars.js @@ -17,6 +17,37 @@ const sidebars = { mySidebar: [ 'Welcome to TurboDocx', + { + type: 'category', + label: 'SDKs', + collapsed: false, + link: { + type: 'doc', + id: 'SDKs/index', + }, + items: [ + { + type: 'doc', + id: 'SDKs/javascript', + label: 'JavaScript / TypeScript', + }, + { + type: 'doc', + id: 'SDKs/python', + label: 'Python', + }, + { + type: 'doc', + id: 'SDKs/go', + label: 'Go', + }, + { + type: 'doc', + id: 'SDKs/java', + label: 'Java', + }, + ], + }, { type: 'category', label: 'TurboDocx Templating',