diff --git a/docs/SDKs/deliverable.md b/docs/SDKs/deliverable.md index d8c2d4dd..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.7.0 + 0.9.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.9.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.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: $_ENV['TURBODOCX_API_KEY'], // Required: Your TurboDocx API key - orgId: $_ENV['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 acd99a7a..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.7.0 + 0.9.0 ``` @@ -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') ?: null, + orgId: getenv('TURBODOCX_ORG_ID') ?: null, + senderEmail: getenv('TURBODOCX_SENDER_EMAIL') ?: null )); // Send a document for signature diff --git a/docs/SDKs/java.md b/docs/SDKs/java.md index f2794937..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.7.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.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.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-java.md b/docs/SDKs/partner-java.md index 35319961..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.7.0 + 0.9.0 ``` @@ -90,14 +90,14 @@ public class Main { ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.0' ``` diff --git a/docs/SDKs/partner-php.md b/docs/SDKs/partner-php.md index 1c84249c..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: $_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 @@ -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. ::: --- @@ -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..fa098149 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') ?: 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 7dc5713b..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.7.0 + 0.9.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.9.0' ``` ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` @@ -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') ?: 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 57bec31a..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.7.0 + 0.9.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.9.0") ``` ```groovy -implementation 'com.turbodocx:turbodocx-sdk:0.7.0' +implementation 'com.turbodocx:turbodocx-sdk:0.9.0' ``` @@ -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') ?: 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) ``` @@ -2965,6 +2967,175 @@ 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. 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`. +::: + + + + +```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 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 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\TurboSign; +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 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 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 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 +``` + + + + +```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 +``` + + + + +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 +5166,23 @@ 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 = 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 ?string $role = null // Template signer role this recipient fills ) {} } @@ -5024,7 +5199,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..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.7.0 + 0.9.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.9.0' ``` ```kotlin -implementation("com.turbodocx:turbodocx-sdk:0.7.0") +implementation("com.turbodocx:turbodocx-sdk:0.9.0") ``` @@ -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') ?: '', // string params: '' makes an unset variable a clear auth error + 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') ?: 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: $_ENV['TURBODOCX_API_KEY'], - orgId: $_ENV['TURBODOCX_ORG_ID'], + 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 = $_ENV['TURBODOCX_WEBHOOK_SECRET']; +$secret = getenv('TURBODOCX_WEBHOOK_SECRET') ?: ''; if (!verifyWebhookSignature($rawBody, $signatureHeader, $timestampHeader, $secret)) { http_response_code(401); @@ -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. 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') {