Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
0aba36d
feat: update js sdk to include advanced templating
K-Kumar-01 Jan 21, 2026
78b39f8
feat: add python sdk for advanced templating support
K-Kumar-01 Jan 21, 2026
02e5dee
feat: add go sdk for advanced templating support
K-Kumar-01 Jan 21, 2026
0c70065
feat: add java sdk for advanced templating
K-Kumar-01 Jan 22, 2026
25e0790
tests: add tests for each sdk
K-Kumar-01 Jan 22, 2026
41513b5
docs: add documentation for deliverable generation
K-Kumar-01 Jan 22, 2026
3d427f4
feat: make mimetype non optional
K-Kumar-01 Jan 22, 2026
ec2752e
fix: remove nested variable property
K-Kumar-01 Jan 22, 2026
0680a27
chore: rename functions to generate advanced engine variable
K-Kumar-01 Jan 22, 2026
3604a31
feat: make placeholder non optional field js and go-sdk
K-Kumar-01 Jan 24, 2026
5589a28
feat: make placeholder non optional field py-sdk
K-Kumar-01 Jan 24, 2026
61b5b8b
feat: make placeholder non optional field java-sdk
K-Kumar-01 Jan 24, 2026
d789c9c
docs: update readme for sdks
K-Kumar-01 Jan 24, 2026
15e909e
tests: update tests for python and go-sdks
K-Kumar-01 Jan 24, 2026
4c8718b
tests: update placeholder and name tests for variables
K-Kumar-01 Jan 24, 2026
9307738
chore: update version
K-Kumar-01 Jan 24, 2026
af2dfd2
fix: handle null/undefined values in generate
K-Kumar-01 Jan 25, 2026
e1ba808
fix: allow null/undefined values for variables
K-Kumar-01 Jan 25, 2026
8536a5c
fix: handle null/undefined values for go sdk
K-Kumar-01 Jan 25, 2026
1427785
fix: http client call
K-Kumar-01 Jan 25, 2026
29f91fd
fix: tests for go sdk
K-Kumar-01 Jan 25, 2026
0154849
fix: mimeTypeJson value
K-Kumar-01 Jan 25, 2026
0f36164
tests: pass mimetype during variable creation
K-Kumar-01 Jan 25, 2026
b71583c
refactor: remove JsonProperty decorator
K-Kumar-01 Jan 25, 2026
9f9e65f
tests: fix tests for java-sdk
K-Kumar-01 Jan 25, 2026
b2972e2
tests: fix test failures for java-sdk
K-Kumar-01 Jan 25, 2026
8273e0a
chore: remove filters reference
K-Kumar-01 Jan 25, 2026
afb8ca8
feat: update php sdk to include deliverbale generation
K-Kumar-01 Jan 25, 2026
5586846
chore: fix php-sdk ci issues
K-Kumar-01 Jan 25, 2026
f0138ce
docs: update php-sdk readme
K-Kumar-01 Jan 25, 2026
e9d8ac5
feat: add sdk for rust
K-Kumar-01 Jan 25, 2026
afba7a5
chore: add ci pipeline for rust
K-Kumar-01 Jan 25, 2026
1248db4
chore: fix formatting issues during ci
K-Kumar-01 Jan 25, 2026
6c83f4b
tests: add manual test suite for go
K-Kumar-01 Jan 29, 2026
2d89e64
tests: add manual test suite for java
K-Kumar-01 Jan 29, 2026
223fae6
tests: add manual test suite for js
K-Kumar-01 Jan 29, 2026
bb51eb4
tests: add manual test suite for php
K-Kumar-01 Jan 29, 2026
5b5ab5a
tests: add manual test suite for python
K-Kumar-01 Jan 29, 2026
8e9a982
tests: add manual test suite for rust
K-Kumar-01 Jan 29, 2026
110a366
fix: remove senderEmail requirement from turbotemplate
K-Kumar-01 Jan 30, 2026
71fd831
fix: remove outputformat value from turbotemplate
K-Kumar-01 Jan 30, 2026
03edcdc
fix: remove senderEmail, outputformat from turbotemplate python sdk
K-Kumar-01 Jan 30, 2026
639c1ba
fix: remove senderEmail, outputformat from turbotemplate sdk-rust
K-Kumar-01 Jan 30, 2026
711f066
fix: remove senderEmail, outputformat from turbotemplate sdk-php
K-Kumar-01 Jan 30, 2026
466287c
fix: remove senderEmail, outputformat from turbotemplate sdk-java
K-Kumar-01 Jan 30, 2026
3a231d9
fix: remove senderEmail, outputformat from turbotemplate sdk-go
K-Kumar-01 Jan 30, 2026
9e65786
fix: typings for variables
K-Kumar-01 Jan 30, 2026
f1975d4
fix: typings for variables in rust
K-Kumar-01 Jan 30, 2026
cc0813b
fix: go sdk responses
K-Kumar-01 Jan 30, 2026
4c063f4
fix: update template response field
K-Kumar-01 Jan 30, 2026
50d2703
feat: update response extraction for php sdk
K-Kumar-01 Jan 30, 2026
4bdd616
fix: unmarshal json response
K-Kumar-01 Jan 30, 2026
c9d3c4b
fix: remove output_format argument
K-Kumar-01 Jan 30, 2026
c284685
docs: update docs for go-sdk
K-Kumar-01 Jan 30, 2026
f27ea3a
refactor: remove error console
K-Kumar-01 Jan 30, 2026
8cd61a2
docs: update docs for sdks
K-Kumar-01 Jan 30, 2026
0b422e6
feat: make name required type
K-Kumar-01 Jan 30, 2026
c5e6a59
chore: make docs and output response type consistent
K-Kumar-01 Jan 31, 2026
ef95f7b
fix: replace deliverableId property with id
K-Kumar-01 Jan 31, 2026
4217896
Merge branch 'main' into ft/advanced_templating
K-Kumar-01 Feb 1, 2026
0e8b09e
feat: add function to download deliverable
K-Kumar-01 Feb 1, 2026
6856854
feat: add function to download deliverable python-sdk
K-Kumar-01 Feb 1, 2026
70675f8
feat: add function to download deliverable php-sdk
K-Kumar-01 Feb 1, 2026
5419a91
feat: add function to download deliverable js-sdk
K-Kumar-01 Feb 1, 2026
bc9d7b3
feat: add function to download deliverable java-sdk
K-Kumar-01 Feb 1, 2026
daf2b00
feat: add function to download deliverable go-sdk
K-Kumar-01 Feb 1, 2026
5850a07
feat: add function to download deliverable rust-sdk
K-Kumar-01 Feb 1, 2026
2c7089d
tests: add automated and manual tests
K-Kumar-01 Feb 1, 2026
3a9f66e
tests: fix js sdk failures
K-Kumar-01 Feb 1, 2026
a85e96c
tests: fix tests for python sdk
K-Kumar-01 Feb 1, 2026
7117df4
tests: fix tests for go sdk
K-Kumar-01 Feb 1, 2026
f4b3684
tests: fix tests for go sdk
K-Kumar-01 Feb 1, 2026
59f3f4c
tests: fix tests for java sdk
K-Kumar-01 Feb 1, 2026
602541d
tests: fix tests for rust sdk; chore: fix formatting errors
K-Kumar-01 Feb 1, 2026
1292830
tests: fix tests for rust sdk
K-Kumar-01 Feb 1, 2026
d15e032
tests: fix tests for php sdk
K-Kumar-01 Feb 1, 2026
bf3856f
ci: fix cippy errors
K-Kumar-01 Feb 1, 2026
87c525f
ci: fix php formatting
K-Kumar-01 Feb 1, 2026
52ac8b4
fix: js example
K-Kumar-01 Feb 3, 2026
006f8d9
fix: auth headers
K-Kumar-01 Feb 3, 2026
81ac70f
fix: response signature
K-Kumar-01 Feb 3, 2026
ba3a8df
fix: rust sdk endpoints
K-Kumar-01 Feb 3, 2026
d3ab566
tests: fix rust test
K-Kumar-01 Feb 3, 2026
1eed275
fix: update void response and examples
K-Kumar-01 Feb 3, 2026
33ba913
ci: update formatting
K-Kumar-01 Feb 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,47 @@ jobs:

- name: Run tests
run: mvn test -B

test-rust:
name: Test Rust SDK
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/rust-sdk
steps:
- uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable

- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}

- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}

- name: Cache target directory
uses: actions/cache@v4
with:
path: packages/rust-sdk/target
key: ${{ runner.os }}-cargo-target-${{ hashFiles('**/Cargo.lock') }}

- name: Check formatting
run: cargo fmt -- --check

- name: Run clippy
run: cargo clippy -- -D warnings

- name: Build
run: cargo build --verbose

- name: Run tests
run: cargo test --verbose
50 changes: 50 additions & 0 deletions .github/workflows/publish-rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Publish Rust SDK

on:
push:
tags:
- 'rust-v*'

jobs:
publish:
name: Publish to crates.io
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/rust-sdk
steps:
- uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable

- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}

- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}

- name: Check formatting
run: cargo fmt -- --check

- name: Run clippy
run: cargo clippy -- -D warnings

- name: Build
run: cargo build --release --verbose

- name: Run tests
run: cargo test --verbose

- name: Publish to crates.io
run: cargo publish --token ${{ secrets.CARGO_TOKEN }}
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_TOKEN }}
117 changes: 109 additions & 8 deletions packages/go-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ import (
)

func main() {
// 1. Create client with sender configuration
// 1. Create client with configuration
client, err := turbodocx.NewClientWithConfig(turbodocx.ClientConfig{
APIKey: os.Getenv("TURBODOCX_API_KEY"), // REQUIRED
OrgID: os.Getenv("TURBODOCX_ORG_ID"), // REQUIRED
SenderEmail: os.Getenv("TURBODOCX_SENDER_EMAIL"), // REQUIRED
SenderName: os.Getenv("TURBODOCX_SENDER_NAME"), // OPTIONAL (but strongly recommended)
SenderEmail: os.Getenv("TURBODOCX_SENDER_EMAIL"), // REQUIRED for TurboSign operations
SenderName: os.Getenv("TURBODOCX_SENDER_NAME"), // OPTIONAL (but recommended for TurboSign)
})
if err != nil {
log.Fatal(err)
Expand Down Expand Up @@ -128,15 +128,21 @@ func main() {
## Configuration

```go
// Basic client configuration (REQUIRED)
// Basic client configuration
client, err := turbodocx.NewClientWithConfig(turbodocx.ClientConfig{
APIKey: "your-api-key", // REQUIRED
OrgID: "your-org-id", // REQUIRED
SenderEmail: "[email protected]", // REQUIRED - reply-to address for signature requests
SenderName: "Your Company", // OPTIONAL but strongly recommended
SenderEmail: "[email protected]", // REQUIRED for TurboSign operations
SenderName: "Your Company", // OPTIONAL (recommended for TurboSign)
})

// With environment variables (recommended)
// For TurboTemplate only (no SenderEmail needed)
client, err := turbodocx.NewClientWithConfig(turbodocx.ClientConfig{
APIKey: os.Getenv("TURBODOCX_API_KEY"),
OrgID: os.Getenv("TURBODOCX_ORG_ID"),
})

// With environment variables (recommended for TurboSign)
client, err := turbodocx.NewClientWithConfig(turbodocx.ClientConfig{
APIKey: os.Getenv("TURBODOCX_API_KEY"),
OrgID: os.Getenv("TURBODOCX_ORG_ID"),
Expand All @@ -155,7 +161,7 @@ client, err := turbodocx.NewClientWithConfig(turbodocx.ClientConfig{
})
```

**Important:** `SenderEmail` is **REQUIRED**. This email will be used as the reply-to address for signature request emails. Without it, emails will default to "API Service User via TurboSign". The `SenderName` is optional but strongly recommended for a professional appearance.
**Important:** `SenderEmail` is **REQUIRED for TurboSign operations**. This email will be used as the reply-to address for signature request emails. For TurboTemplate-only usage, `SenderEmail` is not required. The `SenderName` is optional but strongly recommended for a professional appearance in signature emails.

**Environment Variables:**

Expand Down Expand Up @@ -285,6 +291,101 @@ The audit trail includes a cryptographic hash chain for tamper-evidence verifica

---

### TurboTemplate

Generate documents from templates with advanced variable substitution.

#### `TurboTemplate.Generate`

Generate a document from a template with variables.

```go
result, err := client.TurboTemplate.Generate(ctx, &turbodocx.GenerateTemplateRequest{
TemplateID: "your-template-uuid",
Name: stringPtr("Generated Contract"),
Description: stringPtr("Contract for Q4 2024"),
Variables: []turbodocx.TemplateVariable{
{Placeholder: "{customer_name}", Name: "customer_name", Value: "Acme Corp", MimeType: turbodocx.MimeTypeText},
{Placeholder: "{contract_date}", Name: "contract_date", Value: "2024-01-15", MimeType: turbodocx.MimeTypeText},
{Placeholder: "{total_amount}", Name: "total_amount", Value: 50000, MimeType: turbodocx.MimeTypeText},
},
})

fmt.Printf("Document ID: %s\n", *result.ID)
```

#### Helper Functions

Use helper functions for cleaner variable creation:

```go
// Helper functions return (TemplateVariable, error) - use must() helper for cleaner code
must := func(v turbodocx.TemplateVariable, err error) turbodocx.TemplateVariable {
if err != nil { panic(err) }
return v
}

result, err := client.TurboTemplate.Generate(ctx, &turbodocx.GenerateTemplateRequest{
TemplateID: "invoice-template-uuid",
Name: stringPtr("Invoice #1234"),
Description: stringPtr("Monthly invoice"),
Variables: []turbodocx.TemplateVariable{
// Simple text/number variables (placeholder, name, value, mimeType)
must(turbodocx.NewSimpleVariable("{invoice_number}", "invoice_number", "INV-2024-001", turbodocx.MimeTypeText)),
must(turbodocx.NewSimpleVariable("{total}", "total", 1500, turbodocx.MimeTypeText)),

// Advanced engine variable (placeholder, name, value) - for nested objects with dot notation
must(turbodocx.NewAdvancedEngineVariable("{customer}", "customer", map[string]interface{}{
"name": "Acme Corp",
"email": "[email protected]",
"address": map[string]interface{}{
"street": "123 Main St",
"city": "New York",
"state": "NY",
},
})),

// Arrays for loops (placeholder, name, value) - use {#items}...{/items} in template
must(turbodocx.NewLoopVariable("{items}", "items", []interface{}{
map[string]interface{}{"name": "Widget A", "quantity": 5, "price": 100},
map[string]interface{}{"name": "Widget B", "quantity": 3, "price": 200},
})),

// Conditionals (placeholder, name, value) - use {#is_premium}...{/is_premium} in template
must(turbodocx.NewConditionalVariable("{is_premium}", "is_premium", true)),

// Images (placeholder, name, imageURL)
must(turbodocx.NewImageVariable("{logo}", "logo", "https://example.com/logo.png")),
},
})
```

#### Advanced Templating Features

TurboTemplate supports Angular-like expressions:

| Feature | Template Syntax | Example |
|:--------|:----------------|:--------|
| Simple substitution | `{variable}` | `{customer_name}` |
| Nested objects | `{object.property}` | `{user.address.city}` |
| Loops | `{#array}...{/array}` | `{#items}{name}: ${price}{/items}` |
| Conditionals | `{#condition}...{/condition}` | `{#is_premium}Premium Member{/is_premium}` |
| Expressions | `{expression}` | `{price * quantity}` |

#### Variable Configuration

| Field | Type | Required | Description |
|:------|:-----|:---------|:------------|
| `Placeholder` | string | Yes | The placeholder in template (e.g., `{name}`) |
| `Name` | string | Yes | Variable name for the templating engine |
| `Value` | interface{} | Yes* | The value to substitute |
| `MimeType` | VariableMimeType | Yes | `MimeTypeText`, `MimeTypeJSON`, `MimeTypeHTML`, `MimeTypeImage`, `MimeTypeMarkdown` |
| `UsesAdvancedTemplatingEngine` | *bool | No | Enable for loops, conditionals, expressions |

*Either `Value` or `Text` must be provided.

---

## Field Types

| Type | Description | Required | Auto-filled |
Expand Down
15 changes: 6 additions & 9 deletions packages/go-sdk/client_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,16 @@ import (

// Test senderEmail validation
func TestClientConfig_SenderEmailValidation(t *testing.T) {
t.Run("should throw ValidationError when senderEmail is not provided", func(t *testing.T) {
_, err := NewClientWithConfig(ClientConfig{
t.Run("should not throw error when senderEmail is not provided (optional in Client)", func(t *testing.T) {
// Note: senderEmail validation is done in TurboSign-specific operations, not Client initialization
client, err := NewClientWithConfig(ClientConfig{
APIKey: "test-api-key",
OrgID: "test-org-id",
// senderEmail intentionally missing
// senderEmail intentionally missing - this is valid for Client
})

require.Error(t, err)
validationErr, ok := err.(*ValidationError)
require.True(t, ok, "expected ValidationError")
assert.Contains(t, validationErr.Message, "SenderEmail is required")
assert.Contains(t, validationErr.Message, "reply-to address")
assert.Equal(t, 400, validationErr.StatusCode)
require.NoError(t, err)
assert.NotNil(t, client)
})

t.Run("should accept valid senderEmail", func(t *testing.T) {
Expand Down
Loading
Loading