Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 8 additions & 14 deletions packages/go-sdk/turbosign.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,11 @@ type DocumentStatusResponse struct {

// VoidDocumentResponse is the response from VoidDocument
type VoidDocumentResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
ID string `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
VoidReason string `json:"voidReason,omitempty"`
VoidedAt string `json:"voidedAt,omitempty"`
}

// ResendEmailResponse is the response from ResendEmail
Expand Down Expand Up @@ -245,9 +248,6 @@ func (c *TurboSignClient) CreateSignatureReviewLink(ctx context.Context, req *Cr

if len(req.File) > 0 {
fileName := req.FileName
if fileName == "" {
fileName = "document.pdf"
}
err := c.http.UploadFile(ctx, "/turbosign/single/prepare-for-review", req.File, fileName, formData, &response)
if err != nil {
return nil, err
Expand Down Expand Up @@ -313,9 +313,6 @@ func (c *TurboSignClient) SendSignature(ctx context.Context, req *SendSignatureR

if len(req.File) > 0 {
fileName := req.FileName
if fileName == "" {
fileName = "document.pdf"
}
err := c.http.UploadFile(ctx, "/turbosign/single/prepare-for-signing", req.File, fileName, formData, &response)
if err != nil {
return nil, err
Expand Down Expand Up @@ -387,15 +384,12 @@ func (c *TurboSignClient) Download(ctx context.Context, documentID string) ([]by

// VoidDocument voids a document (cancels signature request)
func (c *TurboSignClient) VoidDocument(ctx context.Context, documentID string, reason string) (*VoidDocumentResponse, error) {
err := c.http.Post(ctx, "/turbosign/documents/"+documentID+"/void", map[string]string{"reason": reason}, nil)
var response VoidDocumentResponse
err := c.http.Post(ctx, "/turbosign/documents/"+documentID+"/void", map[string]string{"reason": reason}, &response)
if err != nil {
return nil, err
}

return &VoidDocumentResponse{
Success: true,
Message: "Document has been voided successfully",
}, nil
return &response, nil
}

// ResendEmail resends signature request email to recipients
Expand Down
16 changes: 12 additions & 4 deletions packages/go-sdk/turbosign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,13 @@ func TestTurboSignClient_VoidDocument(t *testing.T) {
assert.Equal(t, "POST", r.Method)

w.Header().Set("Content-Type", "application/json")
// Backend returns empty response, SDK sets success/message manually
json.NewEncoder(w).Encode(map[string]interface{}{})
json.NewEncoder(w).Encode(map[string]interface{}{
"id": "doc-123",
"name": "Test Document",
"status": "voided",
"voidReason": "Document needs revision",
"voidedAt": "2026-01-26T12:00:00.000Z",
})
}))
defer server.Close()

Expand All @@ -349,8 +354,11 @@ func TestTurboSignClient_VoidDocument(t *testing.T) {
result, err := client.TurboSign.VoidDocument(context.Background(), "doc-123", "Document needs revision")

require.NoError(t, err)
assert.True(t, result.Success)
assert.Equal(t, "Document has been voided successfully", result.Message)
assert.Equal(t, "doc-123", result.ID)
assert.Equal(t, "Test Document", result.Name)
assert.Equal(t, "voided", result.Status)
assert.Equal(t, "Document needs revision", result.VoidReason)
assert.Equal(t, "2026-01-26T12:00:00.000Z", result.VoidedAt)
}

func TestTurboSignClient_ResendEmail(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion packages/java-sdk/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.turbodocx</groupId>
<artifactId>turbodocx-sdk</artifactId>
<version>1.0.0</version>
<version>0.1.2</version>
<packaging>jar</packaging>

<name>TurboDocx SDK</name>
Expand Down
11 changes: 3 additions & 8 deletions packages/java-sdk/src/main/java/com/turbodocx/TurboSign.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public CreateSignatureReviewLinkResponse createSignatureReviewLink(CreateSignatu
);

if (request.hasFile()) {
String fileName = request.getFileName() != null ? request.getFileName() : "document.pdf";
String fileName = request.getFileName();
return httpClient.uploadFile(
"/turbosign/single/prepare-for-review",
request.getFile(),
Expand Down Expand Up @@ -85,7 +85,7 @@ public SendSignatureResponse sendSignature(SendSignatureRequest request) throws
);

if (request.hasFile()) {
String fileName = request.getFileName() != null ? request.getFileName() : "document.pdf";
String fileName = request.getFileName();
return httpClient.uploadFile(
"/turbosign/single/prepare-for-signing",
request.getFile(),
Expand Down Expand Up @@ -158,16 +158,11 @@ public VoidDocumentResponse voidDocument(String documentId, String reason) throw
Map<String, String> body = new HashMap<>();
body.put("reason", reason);

// Backend returns empty data on success, so we just make the call
// and return a success response if no exception is thrown
httpClient.post(
return httpClient.post(
"/turbosign/documents/" + documentId + "/void",
body,
VoidDocumentResponse.class
);

// If we get here without exception, the void was successful
return new VoidDocumentResponse(true, "Document has been voided successfully");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,41 @@
* Response from voiding a document
*/
public class VoidDocumentResponse {
@SerializedName("success")
private Boolean success;
@SerializedName("id")
private String id;

@SerializedName("message")
private String message;
@SerializedName("name")
private String name;

@SerializedName("status")
private String status;

@SerializedName("voidReason")
private String voidReason;

@SerializedName("voidedAt")
private String voidedAt;

// Default constructor for Gson
public VoidDocumentResponse() {}

// Constructor for manual creation (backend returns empty data)
public VoidDocumentResponse(Boolean success, String message) {
this.success = success;
this.message = message;
public String getId() {
return id;
}

public String getName() {
return name;
}

public String getStatus() {
return status;
}

public Boolean getSuccess() {
return success;
public String getVoidReason() {
return voidReason;
}

public String getMessage() {
return message;
public String getVoidedAt() {
return voidedAt;
}
}
16 changes: 12 additions & 4 deletions packages/java-sdk/src/test/java/com/turbodocx/TurboSignTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,16 +345,24 @@ void getStatus() throws Exception {
@Test
@DisplayName("should void a document with reason")
void voidDocument() throws Exception {
// Backend returns empty response, SDK sets success/message manually
server.enqueue(new MockResponse()
.setResponseCode(200)
.setHeader("Content-Type", "application/json")
.setBody(gson.toJson(Map.of())));
.setBody(gson.toJson(Map.of(
"id", "doc-123",
"name", "Test Document",
"status", "voided",
"voidReason", "Document needs revision",
"voidedAt", "2026-01-26T12:00:00.000Z"
))));

VoidDocumentResponse result = client.turboSign().voidDocument("doc-123", "Document needs revision");

assertTrue(result.getSuccess());
assertEquals("Document has been voided successfully", result.getMessage());
assertEquals("doc-123", result.getId());
assertEquals("Test Document", result.getName());
assertEquals("voided", result.getStatus());
assertEquals("Document needs revision", result.getVoidReason());
assertEquals("2026-01-26T12:00:00.000Z", result.getVoidedAt());

RecordedRequest recorded = server.takeRequest();
assertEquals("POST", recorded.getMethod());
Expand Down
2 changes: 1 addition & 1 deletion packages/js-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@turbodocx/sdk",
"version": "0.1.1",
"version": "0.1.2",
"description": "TurboDocx JavaScript SDK - Digital signatures, document generation, and AI-powered workflows",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
16 changes: 5 additions & 11 deletions packages/js-sdk/src/modules/sign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,28 +236,22 @@ export class TurboSign {
*
* @param documentId - ID of the document to void
* @param reason - Reason for voiding the document
* @returns Void confirmation with success and message
* @returns Voided document details including status and timestamp
*
* @example
* ```typescript
* const result = await TurboSign.void(documentId, 'Document needs to be revised');
* console.log(result.message); // "Document has been voided successfully"
* console.log(result.status); // "voided"
* console.log(result.voidedAt); // "2025-01-26T12:00:00.000Z"
* ```
*/
static async void(documentId: string, reason: string): Promise<VoidDocumentResponse> {
const client = this.getClient();
// Backend returns empty data on success, so we just make the call
// and return a success response if no exception is thrown
await client.post(
// HTTP client auto-unwraps {data: ...} responses
return client.post<VoidDocumentResponse>(
`/turbosign/documents/${documentId}/void`,
{ reason }
);

// If we get here without exception, the void was successful
return {
success: true,
message: 'Document has been voided successfully'
};
}

/**
Expand Down
14 changes: 10 additions & 4 deletions packages/js-sdk/src/types/sign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@ export interface RecipientResponse {
}

export interface VoidDocumentResponse {
/** Whether the void was successful */
success: boolean;
/** Response message */
message: string;
/** Document ID */
id: string;
/** Document name */
name: string;
/** Document status (should be 'voided') */
status: string;
/** Reason for voiding */
voidReason?: string;
/** Timestamp when document was voided */
voidedAt?: string;
}

export interface ResendEmailResponse {
Expand Down
16 changes: 12 additions & 4 deletions packages/js-sdk/tests/turbosign.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,9 +468,14 @@ describe("TurboSign Module", () => {

describe("void", () => {
it("should void a document with reason", async () => {
// Backend returns empty response, SDK sets success/message manually
// HTTP client auto-unwraps {data: ...} responses
const mockResponse = {};
const mockResponse = {
id: "doc-123",
name: "Test Document",
status: "voided",
voidReason: "Document needs revision",
voidedAt: "2026-01-26T12:00:00.000Z",
};

MockedHttpClient.prototype.post = jest
.fn()
Expand All @@ -479,8 +484,11 @@ describe("TurboSign Module", () => {

const result = await TurboSign.void("doc-123", "Document needs revision");

expect(result.success).toBe(true);
expect(result.message).toBe("Document has been voided successfully");
expect(result.id).toBe("doc-123");
expect(result.name).toBe("Test Document");
expect(result.status).toBe("voided");
expect(result.voidReason).toBe("Document needs revision");
expect(result.voidedAt).toBe("2026-01-26T12:00:00.000Z");
expect(MockedHttpClient.prototype.post).toHaveBeenCalledWith(
"/turbosign/documents/doc-123/void",
{ reason: "Document needs revision" }
Expand Down
11 changes: 2 additions & 9 deletions packages/php-sdk/src/TurboSign.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,18 +299,11 @@ public static function download(string $documentId): string
public static function void(string $documentId, string $reason): VoidDocumentResponse
{
$client = self::getClient();
// Backend returns empty data on success, so we just make the call
// and return a success response if no exception is thrown
$client->post(
$response = $client->post(
"/turbosign/documents/{$documentId}/void",
['reason' => $reason]
);

// If we get here without exception, the void was successful
return new VoidDocumentResponse(
success: true,
message: 'Document has been voided successfully'
);
return VoidDocumentResponse::fromArray($response);
}

/**
Expand Down
14 changes: 10 additions & 4 deletions packages/php-sdk/src/Types/Responses/VoidDocumentResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
final class VoidDocumentResponse
{
public function __construct(
public bool $success,
public string $message,
public string $id,
public string $name,
public string $status,
public ?string $voidReason = null,
public ?string $voidedAt = null,
) {}

/**
Expand All @@ -23,8 +26,11 @@ public function __construct(
public static function fromArray(array $data): self
{
return new self(
success: $data['success'] ?? true,
message: $data['message'] ?? '',
id: $data['id'] ?? '',
name: $data['name'] ?? '',
status: $data['status'] ?? '',
voidReason: $data['voidReason'] ?? null,
voidedAt: $data['voidedAt'] ?? null,
);
}
}
2 changes: 1 addition & 1 deletion packages/py-sdk/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "turbodocx-sdk"
version = "0.1.0"
version = "0.1.2"
description = "TurboDocx Python SDK - Digital signatures, document generation, and AI-powered workflows"
readme = "README.md"
requires-python = ">=3.9"
Expand Down
Loading
Loading