From d0a74c558b0f10db4556bba605d351dd54a0b36a Mon Sep 17 00:00:00 2001 From: Yacine Kahlerras Date: Tue, 13 Oct 2026 14:31:05 +0100 Subject: [PATCH 1/4] docs(sdks): fix stale Java pin, PHP $_ENV config, readonly claim, JS .env; add send-without-emails section - java.md: 0.7.0 -> 0.8.0 (Maven, Gradle Kotlin, Gradle Groovy). - PHP snippets on php, turbosign, deliverable, webhooks, partner-php, quote and index pages: $_ENV[...] -> getenv(...). $_ENV is empty under the default variables_order = "GPCS". - "readonly classes" is a PHP 8.2 feature; the SDK needs ^8.1 and uses readonly properties. Typed Classes section: Field::$required is ?bool = null (null = required), and Recipient lists phone / externalId / identityVerification. - javascript.md .env adds TURBODOCX_SENDER_EMAIL (required) and TURBODOCX_SENDER_NAME. - turbosign.md: new "Send without emails and sign in your app" section (sendEmail false + createSigningUrl) for JS, Python, PHP, Go and Java, with the Enable identity verification prerequisite. Closes #220 Co-Authored-By: Claude Opus 5.5 --- docs/SDKs/deliverable.md | 4 +- docs/SDKs/index.md | 6 +- docs/SDKs/java.md | 6 +- docs/SDKs/javascript.md | 2 + docs/SDKs/partner-php.md | 8 +- docs/SDKs/php.md | 10 +-- docs/SDKs/quote.md | 4 +- docs/SDKs/turbosign.md | 169 ++++++++++++++++++++++++++++++++++++--- docs/SDKs/webhooks.md | 14 ++-- 9 files changed, 188 insertions(+), 35 deletions(-) diff --git a/docs/SDKs/deliverable.md b/docs/SDKs/deliverable.md index d8c2d4dd..86ea49b9 100644 --- a/docs/SDKs/deliverable.md +++ b/docs/SDKs/deliverable.md @@ -364,8 +364,8 @@ use TurboDocx\Config\DeliverableConfig; // Configure with all options Deliverable::configure(new DeliverableConfig( - apiKey: $_ENV['TURBODOCX_API_KEY'], // Required: Your TurboDocx API key - orgId: $_ENV['TURBODOCX_ORG_ID'], // Required: Your organization ID + apiKey: getenv('TURBODOCX_API_KEY'), // Required: Your TurboDocx API key + orgId: getenv('TURBODOCX_ORG_ID'), // Required: Your organization ID baseUrl: 'https://api.turbodocx.com' // Optional: Custom API endpoint )); ``` diff --git a/docs/SDKs/index.md b/docs/SDKs/index.md index acd99a7a..05bd1fae 100644 --- a/docs/SDKs/index.md +++ b/docs/SDKs/index.md @@ -343,9 +343,9 @@ use TurboDocx\Types\Requests\SendSignatureRequest; // Configure with your API key TurboSign::configure(new HttpClientConfig( - apiKey: $_ENV['TURBODOCX_API_KEY'], - orgId: $_ENV['TURBODOCX_ORG_ID'], - senderEmail: $_ENV['TURBODOCX_SENDER_EMAIL'] + apiKey: getenv('TURBODOCX_API_KEY'), + orgId: getenv('TURBODOCX_ORG_ID'), + senderEmail: getenv('TURBODOCX_SENDER_EMAIL') )); // Send a document for signature diff --git a/docs/SDKs/java.md b/docs/SDKs/java.md index f2794937..b4cc40bc 100644 --- a/docs/SDKs/java.md +++ b/docs/SDKs/java.md @@ -32,7 +32,7 @@ The official TurboDocx SDK for Java applications. Build document generation and com.turbodocx turbodocx-sdk - 0.7.0 + 0.8.0 ``` @@ -40,14 +40,14 @@ The official TurboDocx SDK for Java applications. Build document generation and ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.8.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.8.0' ``` diff --git a/docs/SDKs/javascript.md b/docs/SDKs/javascript.md index c167c480..d65dba24 100644 --- a/docs/SDKs/javascript.md +++ b/docs/SDKs/javascript.md @@ -106,6 +106,8 @@ Authenticate using `apiKey`. API keys are recommended for server-side applicatio # .env TURBODOCX_API_KEY=your_api_key_here TURBODOCX_ORG_ID=your_org_id_here +TURBODOCX_SENDER_EMAIL=you@company.com # Required for TurboSign +TURBODOCX_SENDER_NAME=Your Company Name # Optional (strongly recommended) ``` --- diff --git a/docs/SDKs/partner-php.md b/docs/SDKs/partner-php.md index 1c84249c..885b0c49 100644 --- a/docs/SDKs/partner-php.md +++ b/docs/SDKs/partner-php.md @@ -51,8 +51,8 @@ use TurboDocx\Types\Enums\OrgUserRole; // 1. Configure TurboPartner::configure(new PartnerClientConfig( - partnerApiKey: $_ENV['TURBODOCX_PARTNER_API_KEY'], - partnerId: $_ENV['TURBODOCX_PARTNER_ID'], + partnerApiKey: getenv('TURBODOCX_PARTNER_API_KEY'), + partnerId: getenv('TURBODOCX_PARTNER_ID'), )); // 2. Create an organization with entitlements @@ -114,8 +114,8 @@ use TurboDocx\Config\PartnerClientConfig; // Configure with your partner credentials TurboPartner::configure(new PartnerClientConfig( - partnerApiKey: $_ENV['TURBODOCX_PARTNER_API_KEY'], // Required: Must start with TDXP- - partnerId: $_ENV['TURBODOCX_PARTNER_ID'], // Required: Your partner UUID + partnerApiKey: getenv('TURBODOCX_PARTNER_API_KEY'), // Required: Must start with TDXP- + partnerId: getenv('TURBODOCX_PARTNER_ID'), // Required: Your partner UUID )); ``` diff --git a/docs/SDKs/php.md b/docs/SDKs/php.md index 50635d75..0cefe9b8 100644 --- a/docs/SDKs/php.md +++ b/docs/SDKs/php.md @@ -39,7 +39,7 @@ composer require turbodocx/sdk - ext-fileinfo :::tip Modern PHP Features -This SDK leverages PHP 8.1+ features including enums, named parameters, readonly classes, and match expressions for a superior developer experience. +This SDK leverages PHP 8.1+ features including enums, named parameters, readonly properties, and match expressions for a superior developer experience. ::: --- @@ -57,10 +57,10 @@ use TurboDocx\Config\HttpClientConfig; // Configure with all options TurboSign::configure(new HttpClientConfig( - apiKey: $_ENV['TURBODOCX_API_KEY'], // Required: Your TurboDocx API key - orgId: $_ENV['TURBODOCX_ORG_ID'], // Required: Your organization ID - senderEmail: $_ENV['TURBODOCX_SENDER_EMAIL'], // Required: Reply-to email for signature requests - senderName: $_ENV['TURBODOCX_SENDER_NAME'], // Optional: Sender name (strongly recommended) + apiKey: getenv('TURBODOCX_API_KEY'), // Required: Your TurboDocx API key + orgId: getenv('TURBODOCX_ORG_ID'), // Required: Your organization ID + senderEmail: getenv('TURBODOCX_SENDER_EMAIL'), // Required: Reply-to email for signature requests + senderName: getenv('TURBODOCX_SENDER_NAME'), // Optional: Sender name (strongly recommended) baseUrl: 'https://api.turbodocx.com' // Optional: Custom API endpoint )); ``` diff --git a/docs/SDKs/quote.md b/docs/SDKs/quote.md index 7dc5713b..5e0cf3e1 100644 --- a/docs/SDKs/quote.md +++ b/docs/SDKs/quote.md @@ -414,8 +414,8 @@ use TurboDocx\TurboQuote; use TurboDocx\Config\QuoteClientConfig; TurboQuote::configure(new QuoteClientConfig( - apiKey: $_ENV['TURBODOCX_API_KEY'], - orgId: $_ENV['TURBODOCX_ORG_ID'], // optional, but required for most endpoints + apiKey: getenv('TURBODOCX_API_KEY'), + orgId: getenv('TURBODOCX_ORG_ID'), // optional, but required for most endpoints )); ``` diff --git a/docs/SDKs/turbosign.md b/docs/SDKs/turbosign.md index 57bec31a..4d1cd307 100644 --- a/docs/SDKs/turbosign.md +++ b/docs/SDKs/turbosign.md @@ -254,7 +254,7 @@ bundle install - ext-fileinfo :::tip Modern PHP Features -This SDK leverages PHP 8.1+ features including enums, named parameters, readonly classes, and match expressions for a superior developer experience. +This SDK leverages PHP 8.1+ features including enums, named parameters, readonly properties, and match expressions for a superior developer experience. ::: @@ -361,10 +361,10 @@ use TurboDocx\Config\HttpClientConfig; // Configure with all options TurboSign::configure(new HttpClientConfig( - apiKey: $_ENV['TURBODOCX_API_KEY'], // Required: Your TurboDocx API key - orgId: $_ENV['TURBODOCX_ORG_ID'], // Required: Your organization ID - senderEmail: $_ENV['TURBODOCX_SENDER_EMAIL'], // Required: Reply-to email for signature requests - senderName: $_ENV['TURBODOCX_SENDER_NAME'], // Optional: Sender name (strongly recommended) + apiKey: getenv('TURBODOCX_API_KEY'), // Required: Your TurboDocx API key + orgId: getenv('TURBODOCX_ORG_ID'), // Required: Your organization ID + senderEmail: getenv('TURBODOCX_SENDER_EMAIL'), // Required: Reply-to email for signature requests + senderName: getenv('TURBODOCX_SENDER_NAME'), // Optional: Sender name (strongly recommended) baseUrl: 'https://api.turbodocx.com' // Optional: Custom API endpoint )); ``` @@ -2965,6 +2965,154 @@ puts result["documentId"] +### Send without emails and sign in your app {#send-without-emails} + +Set `sendEmail` to `false` to create the signature request without emailing the signers their links. The document still goes out for signing, and passcode and completed-copy emails are still sent. Then call `createSigningUrl` for a signer when they are ready to sign in your app. Each URL is single-use, so mint it at that moment and don't store it. + +:::info Prerequisite +Embedded signing must be turned on for your organization: in the E-Signature settings, turn on **Enable identity verification** (see [Set up your organization](/docs/TurboSign/how-to-enable-embedded-signing)). While it is off, `createSigningUrl` fails with `EmbeddedSigningNotEnabled`. +::: + + + + +```typescript +const result = await TurboSign.sendSignature({ + fileLink: "https://www.turbodocx.com/examples/turbodocx.pdf", + documentName: "Service Agreement", + 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" }], + sendEmail: false, // no signing-link emails; you hand out the link +}); + +// When the signer is ready, mint their single-use signing URL +const link = await TurboSign.createSigningUrl(result.documentId, { + recipientId: result.recipients![0].id, +}); +console.log(link.url); // open in a new tab or redirect to it +``` + + + + +```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://www.turbodocx.com/examples/turbodocx.pdf", + document_name="Service Agreement", + send_email=False, # no signing-link emails; you hand out the link +) + +# When the signer is ready, mint their single-use signing URL +link = await TurboSign.create_signing_url( + result["documentId"], + recipient_id=result["recipients"][0]["id"], +) +print(link["url"]) # open in a new tab or redirect to it +``` + + + + +```php +use TurboDocx\Types\Recipient; +use TurboDocx\Types\Field; +use TurboDocx\Types\SignatureFieldType; +use TurboDocx\Types\Requests\SendSignatureRequest; +use TurboDocx\Types\Requests\CreateSigningUrlRequest; + +$result = TurboSign::sendSignature( + new SendSignatureRequest( + recipients: [new Recipient('Recipient Name', 'recipient@example.com', 1)], + fields: [ + new Field( + type: SignatureFieldType::SIGNATURE, + recipientEmail: 'recipient@example.com', + page: 1, + x: 100, + y: 500, + width: 200, + height: 50 + ) + ], + fileLink: 'https://www.turbodocx.com/examples/turbodocx.pdf', + documentName: 'Service Agreement', + sendEmail: false // no signing-link emails; you hand out the link + ) +); + +// When the signer is ready, mint their single-use signing URL +$link = TurboSign::createSigningUrl( + $result->documentId, + new CreateSigningUrlRequest(recipientId: $result->recipients[0]['id']) +); +echo $link->url; // open in a new tab or redirect to it +``` + + + + +```go +sendEmail := false // no signing-link emails; you hand out the link +result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{ + FileLink: "https://www.turbodocx.com/examples/turbodocx.pdf", + DocumentName: "Service Agreement", + 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"}, + }, + SendEmail: &sendEmail, +}) +if err != nil { + log.Fatal(err) +} + +// When the signer is ready, mint their single-use signing URL +link, err := client.TurboSign.CreateSigningURL(ctx, result.DocumentID, &turbodocx.CreateSigningURLRequest{ + RecipientID: result.Recipients[0].ID, +}) +if err != nil { + log.Fatal(err) +} +fmt.Println(link.URL) // open in a new tab or redirect to it +``` + + + + +```java +SendSignatureResponse result = client.turboSign().sendSignature( + new SendSignatureRequest.Builder() + .fileLink("https://www.turbodocx.com/examples/turbodocx.pdf") + .documentName("Service Agreement") + .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") + )) + .sendEmail(false) // no signing-link emails; you hand out the link + .build() +); + +// When the signer is ready, mint their single-use signing URL +CreateSigningUrlResponse link = client.turboSign().createSigningUrl( + result.getDocumentId(), + new CreateSigningUrlRequest.Builder() + .recipientId(result.getRecipients().get(0).getId()) + .build() +); +System.out.println(link.getUrl()); // open in a new tab or redirect to it +``` + + + + +To frame the signing page inside your app instead of opening it, and for identity verification options, see [Embedded Signing](/docs/TurboSign/embedded-signing). + ### Reminders and expiration {#reminders-and-expiration} @@ -4995,19 +5143,22 @@ enum ConditionalAction: string { -### Readonly Classes {#readonly-classes} +### Typed Classes {#readonly-classes} -The SDK uses readonly classes with typed properties: +The SDK uses final classes with typed, constructor-promoted properties: ```php final class Recipient { public function __construct( public string $name, public string $email, - public int $signingOrder + public int $signingOrder, + public ?string $phone = null, // E.164; required for SMS passcodes + public ?string $externalId = null, // Your own key, unique in the document + public ?IdentityVerification $identityVerification = null ) {} } @@ -5024,7 +5175,7 @@ final class Field { public ?string $defaultValue = null, // checkbox: 'true'/'false'; date: a fixed MM/DD/YYYY (omit to auto-fill the signing date) public bool $isMultiline = false, public bool $isReadonly = false, - public bool $required = false, + public ?bool $required = null, // null (default) = required; false = optional for the signer public ?string $backgroundColor = null, public ?FieldMetadata $metadata = null // Conditional (IF/THEN) metadata ) {} diff --git a/docs/SDKs/webhooks.md b/docs/SDKs/webhooks.md index 30bbbaeb..ef3f6f46 100644 --- a/docs/SDKs/webhooks.md +++ b/docs/SDKs/webhooks.md @@ -348,8 +348,8 @@ TurboWebhooks.configure( use TurboDocx\TurboWebhooks; TurboWebhooks::configureFromCredentials( - apiKey: $_ENV['TURBODOCX_API_KEY'], - orgId: $_ENV['TURBODOCX_ORG_ID'], + apiKey: getenv('TURBODOCX_API_KEY'), + orgId: getenv('TURBODOCX_ORG_ID'), ); ``` @@ -369,8 +369,8 @@ If you need to build the config yourself, pass `skipSenderValidation: true` — use TurboDocx\Config\HttpClientConfig; TurboWebhooks::configure(new HttpClientConfig( - apiKey: $_ENV['TURBODOCX_API_KEY'], - orgId: $_ENV['TURBODOCX_ORG_ID'], + apiKey: getenv('TURBODOCX_API_KEY'), + orgId: getenv('TURBODOCX_ORG_ID'), skipSenderValidation: true, // webhooks don't send email )); ``` @@ -1189,8 +1189,8 @@ use TurboDocx\Exceptions\ValidationException; use TurboDocx\Types\Enums\WebhookEvent; TurboWebhooks::configureFromCredentials( - apiKey: $_ENV['TURBODOCX_API_KEY'], - orgId: $_ENV['TURBODOCX_ORG_ID'], + apiKey: getenv('TURBODOCX_API_KEY'), + orgId: getenv('TURBODOCX_ORG_ID'), ); try { @@ -1531,7 +1531,7 @@ use function TurboDocx\Utils\verifyWebhookSignature; $rawBody = file_get_contents('php://input'); // raw bytes — do NOT json_decode first $signatureHeader = $_SERVER['HTTP_X_TURBODOCX_SIGNATURE'] ?? ''; $timestampHeader = $_SERVER['HTTP_X_TURBODOCX_TIMESTAMP'] ?? ''; -$secret = $_ENV['TURBODOCX_WEBHOOK_SECRET']; +$secret = getenv('TURBODOCX_WEBHOOK_SECRET'); if (!verifyWebhookSignature($rawBody, $signatureHeader, $timestampHeader, $secret)) { http_response_code(401); From 7da6e492d709768e8019f8d8e0b2b3e6a65202b4 Mon Sep 17 00:00:00 2001 From: Yacine Kahlerras Date: Tue, 13 Oct 2026 14:43:12 +0100 Subject: [PATCH 2/4] docs(sdks): review fixes - all Java pins 0.8.0, reusable-link wording, getenv ?: null - Bump the remaining 0.7.0 Java pins (turbosign, index, deliverable, quote, webhooks, partner-java). The new Java tab needs 0.8.0 (sendEmail / createSigningUrl). - The signing URL in the new section is the reusable signing link for passcode / no-verification signers; only external_idv / override URLs are single-use. - TurboSign page JS .env adds TURBODOCX_SENDER_EMAIL / TURBODOCX_SENDER_NAME. - getenv(...) ?: null for nullable config args, so an unset variable is null (not false) under declare(strict_types=1). - "readonly properties" on the deliverable and partner-php pages too. - Webhook PHP verification sample: getenv('WEBHOOK_SECRET') instead of $_ENV. Co-Authored-By: Claude Opus 5.5 --- docs/SDKs/deliverable.md | 12 ++++----- docs/SDKs/index.md | 8 +++--- docs/SDKs/partner-java.md | 6 ++--- docs/SDKs/partner-php.md | 2 +- docs/SDKs/php.md | 8 +++--- docs/SDKs/quote.md | 10 +++---- docs/SDKs/turbosign.md | 28 +++++++++++--------- docs/SDKs/webhooks.md | 18 ++++++------- static/scripts/webhooks/verification/php.php | 2 +- 9 files changed, 48 insertions(+), 46 deletions(-) diff --git a/docs/SDKs/deliverable.md b/docs/SDKs/deliverable.md index 86ea49b9..7edd6f25 100644 --- a/docs/SDKs/deliverable.md +++ b/docs/SDKs/deliverable.md @@ -173,7 +173,7 @@ go get github.com/TurboDocx/SDK/packages/go-sdk com.turbodocx turbodocx-sdk - 0.7.0 + 0.8.0 ``` @@ -181,14 +181,14 @@ go get github.com/TurboDocx/SDK/packages/go-sdk ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.8.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.8.0' ``` @@ -248,7 +248,7 @@ bundle install - ext-fileinfo :::tip Modern PHP Features -This SDK leverages PHP 8.1+ features including enums, named parameters, readonly classes, and match expressions for a superior developer experience. +This SDK leverages PHP 8.1+ features including enums, named parameters, readonly properties, and match expressions for a superior developer experience. ::: @@ -364,8 +364,8 @@ use TurboDocx\Config\DeliverableConfig; // Configure with all options Deliverable::configure(new DeliverableConfig( - apiKey: getenv('TURBODOCX_API_KEY'), // Required: Your TurboDocx API key - orgId: getenv('TURBODOCX_ORG_ID'), // Required: Your organization ID + apiKey: getenv('TURBODOCX_API_KEY') ?: null, // Required: Your TurboDocx API key + orgId: getenv('TURBODOCX_ORG_ID') ?: null, // Required: Your organization ID baseUrl: 'https://api.turbodocx.com' // Optional: Custom API endpoint )); ``` diff --git a/docs/SDKs/index.md b/docs/SDKs/index.md index 05bd1fae..d35952be 100644 --- a/docs/SDKs/index.md +++ b/docs/SDKs/index.md @@ -204,7 +204,7 @@ go get github.com/TurboDocx/SDK/packages/go-sdk com.turbodocx turbodocx-sdk - 0.7.0 + 0.8.0 ``` @@ -343,9 +343,9 @@ use TurboDocx\Types\Requests\SendSignatureRequest; // Configure with your API key TurboSign::configure(new HttpClientConfig( - apiKey: getenv('TURBODOCX_API_KEY'), - orgId: getenv('TURBODOCX_ORG_ID'), - senderEmail: getenv('TURBODOCX_SENDER_EMAIL') + apiKey: getenv('TURBODOCX_API_KEY') ?: null, + orgId: getenv('TURBODOCX_ORG_ID') ?: null, + senderEmail: getenv('TURBODOCX_SENDER_EMAIL') ?: null )); // Send a document for signature diff --git a/docs/SDKs/partner-java.md b/docs/SDKs/partner-java.md index 35319961..f9fa53fd 100644 --- a/docs/SDKs/partner-java.md +++ b/docs/SDKs/partner-java.md @@ -82,7 +82,7 @@ public class Main { com.turbodocx turbodocx-sdk - 0.7.0 + 0.8.0 ``` @@ -90,14 +90,14 @@ public class Main { ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.8.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.8.0' ``` diff --git a/docs/SDKs/partner-php.md b/docs/SDKs/partner-php.md index 885b0c49..6521e613 100644 --- a/docs/SDKs/partner-php.md +++ b/docs/SDKs/partner-php.md @@ -96,7 +96,7 @@ composer require turbodocx/sdk - ext-curl :::tip Modern PHP Features -This SDK leverages PHP 8.1+ features including enums, named parameters, readonly classes, and match expressions for a superior developer experience. +This SDK leverages PHP 8.1+ features including enums, named parameters, readonly properties, and match expressions for a superior developer experience. ::: --- diff --git a/docs/SDKs/php.md b/docs/SDKs/php.md index 0cefe9b8..fa098149 100644 --- a/docs/SDKs/php.md +++ b/docs/SDKs/php.md @@ -57,10 +57,10 @@ use TurboDocx\Config\HttpClientConfig; // Configure with all options TurboSign::configure(new HttpClientConfig( - apiKey: getenv('TURBODOCX_API_KEY'), // Required: Your TurboDocx API key - orgId: getenv('TURBODOCX_ORG_ID'), // Required: Your organization ID - senderEmail: getenv('TURBODOCX_SENDER_EMAIL'), // Required: Reply-to email for signature requests - senderName: getenv('TURBODOCX_SENDER_NAME'), // Optional: Sender name (strongly recommended) + apiKey: getenv('TURBODOCX_API_KEY') ?: null, // Required: Your TurboDocx API key + orgId: getenv('TURBODOCX_ORG_ID') ?: null, // Required: Your organization ID + senderEmail: getenv('TURBODOCX_SENDER_EMAIL') ?: null, // Required: Reply-to email for signature requests + senderName: getenv('TURBODOCX_SENDER_NAME') ?: null, // Optional: Sender name (strongly recommended) baseUrl: 'https://api.turbodocx.com' // Optional: Custom API endpoint )); ``` diff --git a/docs/SDKs/quote.md b/docs/SDKs/quote.md index 5e0cf3e1..93d1ea59 100644 --- a/docs/SDKs/quote.md +++ b/docs/SDKs/quote.md @@ -234,7 +234,7 @@ import turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" com.turbodocx turbodocx-sdk - 0.7.0 + 0.8.0 ``` @@ -242,14 +242,14 @@ import turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.8.0' ``` ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.8.0") ``` @@ -414,8 +414,8 @@ use TurboDocx\TurboQuote; use TurboDocx\Config\QuoteClientConfig; TurboQuote::configure(new QuoteClientConfig( - apiKey: getenv('TURBODOCX_API_KEY'), - orgId: getenv('TURBODOCX_ORG_ID'), // optional, but required for most endpoints + apiKey: getenv('TURBODOCX_API_KEY') ?: null, + orgId: getenv('TURBODOCX_ORG_ID') ?: null, // optional, but required for most endpoints )); ``` diff --git a/docs/SDKs/turbosign.md b/docs/SDKs/turbosign.md index 4d1cd307..b495d390 100644 --- a/docs/SDKs/turbosign.md +++ b/docs/SDKs/turbosign.md @@ -179,7 +179,7 @@ go get github.com/TurboDocx/SDK/packages/go-sdk com.turbodocx turbodocx-sdk - 0.7.0 + 0.8.0 ``` @@ -187,14 +187,14 @@ go get github.com/TurboDocx/SDK/packages/go-sdk ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.8.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.8.0' ``` @@ -361,10 +361,10 @@ use TurboDocx\Config\HttpClientConfig; // Configure with all options TurboSign::configure(new HttpClientConfig( - apiKey: getenv('TURBODOCX_API_KEY'), // Required: Your TurboDocx API key - orgId: getenv('TURBODOCX_ORG_ID'), // Required: Your organization ID - senderEmail: getenv('TURBODOCX_SENDER_EMAIL'), // Required: Reply-to email for signature requests - senderName: getenv('TURBODOCX_SENDER_NAME'), // Optional: Sender name (strongly recommended) + apiKey: getenv('TURBODOCX_API_KEY') ?: null, // Required: Your TurboDocx API key + orgId: getenv('TURBODOCX_ORG_ID') ?: null, // Required: Your organization ID + senderEmail: getenv('TURBODOCX_SENDER_EMAIL') ?: null, // Required: Reply-to email for signature requests + senderName: getenv('TURBODOCX_SENDER_NAME') ?: null, // Optional: Sender name (strongly recommended) baseUrl: 'https://api.turbodocx.com' // Optional: Custom API endpoint )); ``` @@ -547,6 +547,8 @@ Creating a client per request leaks OkHttp threads until they are closed. Prefer # .env TURBODOCX_API_KEY=your_api_key_here TURBODOCX_ORG_ID=your_org_id_here +TURBODOCX_SENDER_EMAIL=you@company.com # Required for TurboSign +TURBODOCX_SENDER_NAME=Your Company Name # Optional (strongly recommended) ``` @@ -2967,7 +2969,7 @@ puts result["documentId"] ### Send without emails and sign in your app {#send-without-emails} -Set `sendEmail` to `false` to create the signature request without emailing the signers their links. The document still goes out for signing, and passcode and completed-copy emails are still sent. Then call `createSigningUrl` for a signer when they are ready to sign in your app. Each URL is single-use, so mint it at that moment and don't store it. +Set `sendEmail` to `false` to create the signature request without emailing the signers their links. The document still goes out for signing, and passcode and completed-copy emails are still sent. Then call `createSigningUrl` for a signer when they are ready to sign in your app. For a signer with an email/SMS passcode or no verification (as here), the URL is their reusable signing link for the life of the document, so treat it like a password and don't log it. `external_idv` and `override` signers get a single-use URL that expires in about five minutes; mint those at the moment of signing. :::info Prerequisite Embedded signing must be turned on for your organization: in the E-Signature settings, turn on **Enable identity verification** (see [Set up your organization](/docs/TurboSign/how-to-enable-embedded-signing)). While it is off, `createSigningUrl` fails with `EmbeddedSigningNotEnabled`. @@ -2985,7 +2987,7 @@ const result = await TurboSign.sendSignature({ sendEmail: false, // no signing-link emails; you hand out the link }); -// When the signer is ready, mint their single-use signing URL +// When the signer is ready, mint their signing URL const link = await TurboSign.createSigningUrl(result.documentId, { recipientId: result.recipients![0].id, }); @@ -3004,7 +3006,7 @@ result = await TurboSign.send_signature( send_email=False, # no signing-link emails; you hand out the link ) -# When the signer is ready, mint their single-use signing URL +# When the signer is ready, mint their signing URL link = await TurboSign.create_signing_url( result["documentId"], recipient_id=result["recipients"][0]["id"], @@ -3042,7 +3044,7 @@ $result = TurboSign::sendSignature( ) ); -// When the signer is ready, mint their single-use signing URL +// When the signer is ready, mint their signing URL $link = TurboSign::createSigningUrl( $result->documentId, new CreateSigningUrlRequest(recipientId: $result->recipients[0]['id']) @@ -3070,7 +3072,7 @@ if err != nil { log.Fatal(err) } -// When the signer is ready, mint their single-use signing URL +// When the signer is ready, mint their signing URL link, err := client.TurboSign.CreateSigningURL(ctx, result.DocumentID, &turbodocx.CreateSigningURLRequest{ RecipientID: result.Recipients[0].ID, }) @@ -3098,7 +3100,7 @@ SendSignatureResponse result = client.turboSign().sendSignature( .build() ); -// When the signer is ready, mint their single-use signing URL +// When the signer is ready, mint their signing URL CreateSigningUrlResponse link = client.turboSign().createSigningUrl( result.getDocumentId(), new CreateSigningUrlRequest.Builder() diff --git a/docs/SDKs/webhooks.md b/docs/SDKs/webhooks.md index ef3f6f46..dd904272 100644 --- a/docs/SDKs/webhooks.md +++ b/docs/SDKs/webhooks.md @@ -213,7 +213,7 @@ import turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" com.turbodocx turbodocx-sdk - 0.7.0 + 0.8.0 ``` @@ -221,14 +221,14 @@ import turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.8.0' ``` ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.8.0") ``` @@ -348,8 +348,8 @@ TurboWebhooks.configure( use TurboDocx\TurboWebhooks; TurboWebhooks::configureFromCredentials( - apiKey: getenv('TURBODOCX_API_KEY'), - orgId: getenv('TURBODOCX_ORG_ID'), + apiKey: getenv('TURBODOCX_API_KEY') ?: null, + orgId: getenv('TURBODOCX_ORG_ID') ?: null, ); ``` @@ -369,8 +369,8 @@ If you need to build the config yourself, pass `skipSenderValidation: true` — use TurboDocx\Config\HttpClientConfig; TurboWebhooks::configure(new HttpClientConfig( - apiKey: getenv('TURBODOCX_API_KEY'), - orgId: getenv('TURBODOCX_ORG_ID'), + apiKey: getenv('TURBODOCX_API_KEY') ?: null, + orgId: getenv('TURBODOCX_ORG_ID') ?: null, skipSenderValidation: true, // webhooks don't send email )); ``` @@ -1189,8 +1189,8 @@ use TurboDocx\Exceptions\ValidationException; use TurboDocx\Types\Enums\WebhookEvent; TurboWebhooks::configureFromCredentials( - apiKey: getenv('TURBODOCX_API_KEY'), - orgId: getenv('TURBODOCX_ORG_ID'), + apiKey: getenv('TURBODOCX_API_KEY') ?: null, + orgId: getenv('TURBODOCX_ORG_ID') ?: null, ); try { diff --git a/static/scripts/webhooks/verification/php.php b/static/scripts/webhooks/verification/php.php index d7118fb0..d330f978 100644 --- a/static/scripts/webhooks/verification/php.php +++ b/static/scripts/webhooks/verification/php.php @@ -185,7 +185,7 @@ function testWebhookVerification(string $secret = 'test-secret'): bool // Example usage when script is run directly if (__FILE__ === $_SERVER['SCRIPT_FILENAME']) { - $webhookSecret = $_ENV['WEBHOOK_SECRET'] ?? 'your-webhook-secret'; + $webhookSecret = getenv('WEBHOOK_SECRET') ?: 'your-webhook-secret'; // If running from command line, run test if (php_sapi_name() === 'cli') { From 0f6b2a3778921bd41cddb3d158be45eee70185f8 Mon Sep 17 00:00:00 2001 From: Yacine Kahlerras Date: Wed, 14 Oct 2026 10:50:06 +0100 Subject: [PATCH 3/4] docs(sdks): round-2 review fixes - getenv ?: '' for string params, PHP tab import - TurboWebhooks::configureFromCredentials() and PartnerClientConfig take non-nullable strings: `?: null` turned an unset variable into a TypeError. Use `?: ''`, which gives the SDK's clear AuthenticationException (matches fromEnvironment()). Same for the webhook receiver's secret, so an unset secret fails closed (401) instead of a TypeError (500) under strict_types. - The new PHP tab now imports TurboDocx\TurboSign like every other PHP tab. Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/SDKs/partner-php.md | 8 ++++---- docs/SDKs/turbosign.md | 1 + docs/SDKs/webhooks.md | 10 +++++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/SDKs/partner-php.md b/docs/SDKs/partner-php.md index 6521e613..98c651e6 100644 --- a/docs/SDKs/partner-php.md +++ b/docs/SDKs/partner-php.md @@ -51,8 +51,8 @@ use TurboDocx\Types\Enums\OrgUserRole; // 1. Configure TurboPartner::configure(new PartnerClientConfig( - partnerApiKey: getenv('TURBODOCX_PARTNER_API_KEY'), - partnerId: getenv('TURBODOCX_PARTNER_ID'), + partnerApiKey: getenv('TURBODOCX_PARTNER_API_KEY') ?: '', + partnerId: getenv('TURBODOCX_PARTNER_ID') ?: '', )); // 2. Create an organization with entitlements @@ -114,8 +114,8 @@ use TurboDocx\Config\PartnerClientConfig; // Configure with your partner credentials TurboPartner::configure(new PartnerClientConfig( - partnerApiKey: getenv('TURBODOCX_PARTNER_API_KEY'), // Required: Must start with TDXP- - partnerId: getenv('TURBODOCX_PARTNER_ID'), // Required: Your partner UUID + partnerApiKey: getenv('TURBODOCX_PARTNER_API_KEY') ?: '', // Required: Must start with TDXP- + partnerId: getenv('TURBODOCX_PARTNER_ID') ?: '', // Required: Your partner UUID )); ``` diff --git a/docs/SDKs/turbosign.md b/docs/SDKs/turbosign.md index b495d390..4366102d 100644 --- a/docs/SDKs/turbosign.md +++ b/docs/SDKs/turbosign.md @@ -3018,6 +3018,7 @@ print(link["url"]) # open in a new tab or redirect to it ```php +use TurboDocx\TurboSign; use TurboDocx\Types\Recipient; use TurboDocx\Types\Field; use TurboDocx\Types\SignatureFieldType; diff --git a/docs/SDKs/webhooks.md b/docs/SDKs/webhooks.md index dd904272..062a113b 100644 --- a/docs/SDKs/webhooks.md +++ b/docs/SDKs/webhooks.md @@ -348,8 +348,8 @@ TurboWebhooks.configure( use TurboDocx\TurboWebhooks; TurboWebhooks::configureFromCredentials( - apiKey: getenv('TURBODOCX_API_KEY') ?: null, - orgId: getenv('TURBODOCX_ORG_ID') ?: null, + apiKey: getenv('TURBODOCX_API_KEY') ?: '', // string params: '' makes an unset variable a clear auth error + orgId: getenv('TURBODOCX_ORG_ID') ?: '', ); ``` @@ -1189,8 +1189,8 @@ use TurboDocx\Exceptions\ValidationException; use TurboDocx\Types\Enums\WebhookEvent; TurboWebhooks::configureFromCredentials( - apiKey: getenv('TURBODOCX_API_KEY') ?: null, - orgId: getenv('TURBODOCX_ORG_ID') ?: null, + apiKey: getenv('TURBODOCX_API_KEY') ?: '', // string params: '' makes an unset variable a clear auth error + orgId: getenv('TURBODOCX_ORG_ID') ?: '', ); try { @@ -1531,7 +1531,7 @@ use function TurboDocx\Utils\verifyWebhookSignature; $rawBody = file_get_contents('php://input'); // raw bytes — do NOT json_decode first $signatureHeader = $_SERVER['HTTP_X_TURBODOCX_SIGNATURE'] ?? ''; $timestampHeader = $_SERVER['HTTP_X_TURBODOCX_TIMESTAMP'] ?? ''; -$secret = getenv('TURBODOCX_WEBHOOK_SECRET'); +$secret = getenv('TURBODOCX_WEBHOOK_SECRET') ?: ''; if (!verifyWebhookSignature($rawBody, $signatureHeader, $timestampHeader, $secret)) { http_response_code(401); From 6be3463bd77d84f6dabe107d95b41777c7c2f9f8 Mon Sep 17 00:00:00 2001 From: Amit Sharma Date: Wed, 21 Oct 2026 17:15:00 +0530 Subject: [PATCH 4/4] docs(sdks): match the 0.9.0 SDKs and add the Ruby tab to send-without-emails (#220) - Java pins 0.8.0 -> 0.9.0 (the published version since 2026-10-20) on every SDK page. - Send without emails: a Ruby tab; say the opt-out also covers the initial CC email, later signers' turn emails and scheduled reminders; recipients is always present on the JS response in 0.9.0, so no non-null assertion. - PHP Typed Classes: Recipient's signingOrder is optional when the recipient has a role, and role is new in 0.9.0. - Go webhook verification: 0.9.0 treats ToleranceSeconds 0 as the 300s default and rejects every delivery on a negative value; -1 no longer disables the timestamp check. Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/SDKs/deliverable.md | 6 +++--- docs/SDKs/index.md | 2 +- docs/SDKs/java.md | 6 +++--- docs/SDKs/partner-java.md | 6 +++--- docs/SDKs/quote.md | 6 +++--- docs/SDKs/turbosign.md | 35 ++++++++++++++++++++++++++++------- docs/SDKs/webhooks.md | 8 ++++---- 7 files changed, 45 insertions(+), 24 deletions(-) diff --git a/docs/SDKs/deliverable.md b/docs/SDKs/deliverable.md index 7edd6f25..e3607d44 100644 --- a/docs/SDKs/deliverable.md +++ b/docs/SDKs/deliverable.md @@ -173,7 +173,7 @@ go get github.com/TurboDocx/SDK/packages/go-sdk com.turbodocx turbodocx-sdk - 0.8.0 + 0.9.0 ``` @@ -181,14 +181,14 @@ go get github.com/TurboDocx/SDK/packages/go-sdk ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.8.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.8.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.0' ``` diff --git a/docs/SDKs/index.md b/docs/SDKs/index.md index d35952be..70565a27 100644 --- a/docs/SDKs/index.md +++ b/docs/SDKs/index.md @@ -204,7 +204,7 @@ go get github.com/TurboDocx/SDK/packages/go-sdk com.turbodocx turbodocx-sdk - 0.8.0 + 0.9.0 ``` diff --git a/docs/SDKs/java.md b/docs/SDKs/java.md index b4cc40bc..7827f850 100644 --- a/docs/SDKs/java.md +++ b/docs/SDKs/java.md @@ -32,7 +32,7 @@ The official TurboDocx SDK for Java applications. Build document generation and com.turbodocx turbodocx-sdk - 0.8.0 + 0.9.0 ``` @@ -40,14 +40,14 @@ The official TurboDocx SDK for Java applications. Build document generation and ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.8.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.8.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.0' ``` diff --git a/docs/SDKs/partner-java.md b/docs/SDKs/partner-java.md index f9fa53fd..1173a535 100644 --- a/docs/SDKs/partner-java.md +++ b/docs/SDKs/partner-java.md @@ -82,7 +82,7 @@ public class Main { com.turbodocx turbodocx-sdk - 0.8.0 + 0.9.0 ``` @@ -90,14 +90,14 @@ public class Main { ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.8.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.8.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.0' ``` diff --git a/docs/SDKs/quote.md b/docs/SDKs/quote.md index 93d1ea59..90321558 100644 --- a/docs/SDKs/quote.md +++ b/docs/SDKs/quote.md @@ -234,7 +234,7 @@ import turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" com.turbodocx turbodocx-sdk - 0.8.0 + 0.9.0 ``` @@ -242,14 +242,14 @@ import turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.8.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.0' ``` ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.8.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` diff --git a/docs/SDKs/turbosign.md b/docs/SDKs/turbosign.md index 4366102d..e6213914 100644 --- a/docs/SDKs/turbosign.md +++ b/docs/SDKs/turbosign.md @@ -179,7 +179,7 @@ go get github.com/TurboDocx/SDK/packages/go-sdk com.turbodocx turbodocx-sdk - 0.8.0 + 0.9.0 ``` @@ -187,14 +187,14 @@ go get github.com/TurboDocx/SDK/packages/go-sdk ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.8.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.8.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.0' ``` @@ -2969,7 +2969,7 @@ puts result["documentId"] ### Send without emails and sign in your app {#send-without-emails} -Set `sendEmail` to `false` to create the signature request without emailing the signers their links. The document still goes out for signing, and passcode and completed-copy emails are still sent. Then call `createSigningUrl` for a signer when they are ready to sign in your app. For a signer with an email/SMS passcode or no verification (as here), the URL is their reusable signing link for the life of the document, so treat it like a password and don't log it. `external_idv` and `override` signers get a single-use URL that expires in about five minutes; mint those at the moment of signing. +Set `sendEmail` to `false` to create the signature request without emailing the signers their links. The document still goes out for signing, and passcode and completed-copy emails are still sent. The opt-out also covers the initial CC email, later signers' turn emails and scheduled reminders. Then call `createSigningUrl` for a signer when they are ready to sign in your app. For a signer with an email/SMS passcode or no verification (as here), the URL is their reusable signing link for the life of the document, so treat it like a password and don't log it. `external_idv` and `override` signers get a single-use URL that expires in about five minutes; mint those at the moment of signing. :::info Prerequisite Embedded signing must be turned on for your organization: in the E-Signature settings, turn on **Enable identity verification** (see [Set up your organization](/docs/TurboSign/how-to-enable-embedded-signing)). While it is off, `createSigningUrl` fails with `EmbeddedSigningNotEnabled`. @@ -2989,7 +2989,7 @@ const result = await TurboSign.sendSignature({ // When the signer is ready, mint their signing URL const link = await TurboSign.createSigningUrl(result.documentId, { - recipientId: result.recipients![0].id, + recipientId: result.recipients[0].id, }); console.log(link.url); // open in a new tab or redirect to it ``` @@ -3111,6 +3111,26 @@ CreateSigningUrlResponse link = client.turboSign().createSigningUrl( System.out.println(link.getUrl()); // open in a new tab or redirect to it ``` + + + +```ruby +result = TurboDocxSdk::TurboSign.send_signature( + fileLink: "https://www.turbodocx.com/examples/turbodocx.pdf", + documentName: "Service Agreement", + 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" }], + sendEmail: false # no signing-link emails; you hand out the link +) + +# When the signer is ready, mint their signing URL +link = TurboDocxSdk::TurboSign.create_signing_url( + result["documentId"], + recipient_id: result["recipients"][0]["id"] +) +puts link["url"] # open in a new tab or redirect to it +``` + @@ -5158,10 +5178,11 @@ final class Recipient { public function __construct( public string $name, public string $email, - public int $signingOrder, + public ?int $signingOrder = null, // Required unless the recipient has a role public ?string $phone = null, // E.164; required for SMS passcodes public ?string $externalId = null, // Your own key, unique in the document - public ?IdentityVerification $identityVerification = null + public ?IdentityVerification $identityVerification = null, + public ?string $role = null // Template signer role this recipient fills ) {} } diff --git a/docs/SDKs/webhooks.md b/docs/SDKs/webhooks.md index 062a113b..d9c100ee 100644 --- a/docs/SDKs/webhooks.md +++ b/docs/SDKs/webhooks.md @@ -213,7 +213,7 @@ import turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" com.turbodocx turbodocx-sdk - 0.8.0 + 0.9.0 ``` @@ -221,14 +221,14 @@ import turbodocx "github.com/TurboDocx/SDK/packages/go-sdk" ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.8.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.0' ``` ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.8.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` @@ -2952,7 +2952,7 @@ ok := turbodocx.VerifyWebhookSignature( ) ``` -Pass `&turbodocx.VerifyWebhookSignatureOptions{ToleranceSeconds: 60}` to tighten the window, or `ToleranceSeconds: -1` to disable the timestamp check entirely (NOT recommended in production). +Pass `&turbodocx.VerifyWebhookSignatureOptions{ToleranceSeconds: 60}` to tighten the window, or a larger positive value to widen it. `0` (the zero value) means the 300-second default, so the Go helper has no way to turn the timestamp check off, and a negative value rejects every delivery.