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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ Skip the product selection prompt:
### TurboSign Integration
- Client configuration with env var loading
- `sendSignature()`, `getStatus()`, `download()` — send, track, retrieve signed PDFs
- Conditional (IF/THEN) fields — a controlling `checkbox` plus dependent fields that show or unlock only when it is ticked (via optional field `metadata`)
- Optional: `void()`, `resend()`, `getAuditTrail()` — cancellation, reminders, tamper-evident audit log
- Route handlers wired into your existing app

Expand Down
58 changes: 58 additions & 0 deletions evals/evals.json
Original file line number Diff line number Diff line change
Expand Up @@ -1229,6 +1229,64 @@
}
]
},
{
"id": 51,
"prompt": "Set up TurboSign in my Express app. On the signing document I need a conditional field: the signer ticks a checkbox to opt into relocation assistance, and only then should a second signature field become visible. Add an endpoint that sends this document.",
"expected_output": "Creates a TurboSign config file and a sendSignature endpoint whose fields array contains a controlling checkbox field with metadata.fieldKey and a dependent field with metadata.conditional (controllingFieldKey matching the checkbox fieldKey, operator is_checked, action show), wires routes into the main app, adds .env with TurboSign vars",
"files": [
"package.json",
"tsconfig.json",
"src/index.ts",
"package-lock.json"
],
"assertions": [
{
"name": "config-file-created",
"type": "file_exists",
"description": "A TurboSign config/client file was created"
},
{
"name": "uses-sendSignature",
"type": "file_contains",
"description": "Route handler calls TurboSign.sendSignature with a fields array"
},
{
"name": "has-checkbox-field",
"type": "file_contains",
"description": "The fields array includes a field with type 'checkbox' acting as the controlling field"
},
{
"name": "checkbox-has-fieldKey",
"type": "file_contains",
"description": "The controlling checkbox field carries metadata.fieldKey (a stable id, e.g. metadata: { fieldKey: '...' })"
},
{
"name": "dependent-has-conditional",
"type": "file_contains",
"description": "A dependent field carries metadata.conditional with controllingFieldKey, operator, and action keys"
},
{
"name": "controllingFieldKey-matches",
"type": "file_contains",
"description": "The dependent field's conditional.controllingFieldKey matches the controlling checkbox's metadata.fieldKey value exactly"
},
{
"name": "uses-valid-operator-and-action",
"type": "file_contains",
"description": "conditional.operator is 'is_checked' or 'is_not_checked' and conditional.action is 'show' or 'unlock'"
},
{
"name": "routes-wired",
"type": "file_contains",
"description": "Main app file (src/index.ts) was modified to import and register the signature routes"
},
{
"name": "env-has-sign-vars",
"type": "file_contains",
"description": ".env contains TURBODOCX_API_KEY and TURBODOCX_SENDER_EMAIL"
}
]
},
{
"id": 10,
"skill_name": "turbodocx-html-to-docx",
Expand Down
1 change: 1 addition & 0 deletions skills/turbodocx-sdk/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ Create working route handlers / endpoint code for the selected product(s). The l

**For TurboSign, generate:**
- `sendSignature()` endpoint — accepts file (or `fileLink` / `deliverableId` / `templateId`), recipients, fields
- If the user wants **conditional (IF/THEN) fields** — a field that shows or unlocks only when the signer ticks a box: add a controlling `checkbox` field carrying `metadata.fieldKey`, and a dependent field carrying `metadata.conditional` (`{ controllingFieldKey, operator: "is_checked" | "is_not_checked", action: "show" | "unlock" }`) whose `controllingFieldKey` matches the checkbox's `fieldKey`. `action: "show"` keeps the dependent field hidden until the condition is met; `action: "unlock"` shows it but read-only until met. `metadata` is optional and both live on the normal `sendSignature()` field array — see the language reference for the exact per-language shape.
- `getStatus()` endpoint — check the document-level status by ID
- `getRecipients()` endpoint — every recipient with their signing status, email history, and who sent the document. Generate this whenever the user wants to know **who has signed / who is still pending**; `getStatus()` alone cannot answer that. Note each recipient carries both `status` (raw: `pending`/`viewed`/`completed`) and `effectiveStatus` (adds `voided`/`expired`) — generated code should branch on `effectiveStatus`, since an unsigned signer on a voided document still reads `pending` in the raw field.
- `download()` endpoint — stream signed PDF (returns `Blob`/`ArrayBuffer` per language)
Expand Down
52 changes: 52 additions & 0 deletions skills/turbodocx-sdk/references/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,58 @@ if err != nil {
fmt.Printf("Document ID: %s\n", result.DocumentID)
```

### Conditional (IF/THEN) fields

Any field can be made to depend on a **controlling checkbox** so it only appears — or only becomes editable — once the signer ticks that box. Give the checkbox a stable `Metadata.FieldKey`, then reference that key from the dependent field's `Metadata.Conditional.ControllingFieldKey`. `Field.Metadata` is an **optional** `*turbodocx.FieldMetadata`; a nil `Metadata` (the default) behaves exactly as before.

```go
result, err := client.TurboSign.SendSignature(ctx, &turbodocx.SendSignatureRequest{
File: pdfFile,
FileName: "contract.pdf",
DocumentName: "Employment Agreement",
Recipients: []turbodocx.Recipient{
{Name: "John Doe", Email: "john@example.com", SigningOrder: 1},
},
Fields: []turbodocx.Field{
// Controlling checkbox — the box the signer ticks. Its FieldKey is the stable id others reference.
{
Type: "checkbox",
RecipientEmail: "john@example.com",
Page: 1,
X: 100,
Y: 400,
Width: 20,
Height: 20,
Metadata: &turbodocx.FieldMetadata{
FieldKey: "relocation_optin",
},
},
// Dependent field — hidden until the box above is checked (Action: "show").
{
Type: "signature",
RecipientEmail: "john@example.com",
Page: 1,
X: 100,
Y: 460,
Width: 200,
Height: 50,
Metadata: &turbodocx.FieldMetadata{
Conditional: &turbodocx.FieldConditional{
ControllingFieldKey: "relocation_optin", // = the checkbox's Metadata.FieldKey
Operator: "is_checked", // "is_checked" | "is_not_checked"
Action: "show", // "show" = hidden until met; "unlock" = visible but read-only until met
},
},
},
},
})
if err != nil {
log.Fatal(err)
}
```

The link is `FieldKey` → `ControllingFieldKey`: the two strings must match exactly (the checkbox carries `Metadata.FieldKey`, the dependent field points at it via `Metadata.Conditional.ControllingFieldKey`). `Operator` chooses which checkbox state satisfies the condition — `"is_checked"` or `"is_not_checked"`. `Action` chooses what happens while the condition is unmet: `"show"` keeps the dependent field **hidden until met**, while `"unlock"` renders it **visible but read-only (locked) until met**.

### GetStatus

```go
Expand Down
43 changes: 43 additions & 0 deletions skills/turbodocx-sdk/references/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,49 @@ SendSignatureResponse result = client.turboSign().sendSignature(
System.out.println("Document ID: " + result.getDocumentId());
```

### Conditional (IF/THEN) fields

Any field can be made to depend on a **controlling checkbox** so it only appears — or only becomes editable — once the signer ticks that box. Give the checkbox a stable `FieldMetadata` with a `fieldKey`, then reference that key from the dependent field's `FieldMetadata` → `FieldConditional` → `controllingFieldKey`. `.metadata(...)` on the builder is **optional**; a field left without it behaves exactly as before.

```java
SendSignatureResponse result = client.turboSign().sendSignature(
new SendSignatureRequest.Builder()
.file(pdfFile)
.fileName("contract.pdf")
.documentName("Employment Agreement")
.recipients(Arrays.asList(
new Recipient("John Doe", "john@example.com", 1)
))
.fields(Arrays.asList(
// Controlling checkbox — the box the signer ticks. Its fieldKey is the stable id others reference.
new Field.Builder()
.type("checkbox")
.recipientEmail("john@example.com")
.page(1)
.x(100).y(400).width(20).height(20)
.metadata(FieldMetadata.forFieldKey("relocation_optin"))
.build(),
// Dependent field — hidden until the box above is checked (action "show").
new Field.Builder()
.type("signature")
.recipientEmail("john@example.com")
.page(1)
.x(100).y(460).width(200).height(50)
.metadata(FieldMetadata.forConditional(
new FieldConditional(
"relocation_optin", // controllingFieldKey = the checkbox's metadata fieldKey
"is_checked", // "is_checked" | "is_not_checked"
"show"))) // "show" = hidden until met; "unlock" = visible but read-only until met
.build()
))
.build()
);

System.out.println("Document ID: " + result.getDocumentId());
```

The link is `fieldKey` → `controllingFieldKey`: the two strings must match exactly (the checkbox carries `FieldMetadata.fieldKey`, the dependent field points at it via `FieldConditional.controllingFieldKey`). `operator` chooses which checkbox state satisfies the condition — `"is_checked"` or `"is_not_checked"`. `action` chooses what happens while the condition is unmet: `"show"` keeps the dependent field **hidden until met**, while `"unlock"` renders it **visible but read-only (locked) until met**.

### getStatus

```java
Expand Down
38 changes: 38 additions & 0 deletions skills/turbodocx-sdk/references/javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,44 @@ console.log(result.recipients); // ReviewRecipient[] with { id, name, email, m

Fields support either coordinate-based (`page` + `x` / `y` / `width` / `height`) or anchor-based placement via `template: { anchor: '{TagName}', placement: 'replace', size: {...} }`.

### Conditional (IF/THEN) fields

Any field can be made to depend on a **controlling checkbox** so it only appears — or only becomes editable — once the signer ticks that box. Give the checkbox a stable `metadata.fieldKey`, then reference that key from the dependent field's `metadata.conditional.controllingFieldKey`. Both live in an **optional** `metadata` object on the field; fields without it behave exactly as before.

```typescript
const result = await TurboSign.sendSignature({
file: pdfBuffer,
documentName: 'Employment Agreement',
recipients: [
{ name: 'John Doe', email: 'john@example.com', signingOrder: 1 },
],
fields: [
// Controlling checkbox — the box the signer ticks. Its metadata.fieldKey is the stable id others reference.
{
type: 'checkbox',
page: 1, x: 100, y: 400, width: 20, height: 20,
recipientEmail: 'john@example.com',
metadata: { fieldKey: 'relocation_optin' },
},
// Dependent field — hidden until the box above is checked (action: 'show').
{
type: 'signature',
page: 1, x: 100, y: 460, width: 200, height: 50,
recipientEmail: 'john@example.com',
metadata: {
conditional: {
controllingFieldKey: 'relocation_optin', // = the checkbox's metadata.fieldKey
operator: 'is_checked', // 'is_checked' | 'is_not_checked'
action: 'show', // 'show' = hidden until met; 'unlock' = visible but read-only until met
},
},
},
],
});
```

The link is `fieldKey` → `controllingFieldKey`: the two strings must match exactly (the checkbox carries `metadata.fieldKey`, the dependent field points at it via `metadata.conditional.controllingFieldKey`). `operator` chooses which checkbox state satisfies the condition — `is_checked` or `is_not_checked`. `action` chooses what happens while the condition is unmet: `show` keeps the dependent field **hidden until met**, while `unlock` renders it **visible but read-only (locked) until met**.

### TurboSign.getStatus

```typescript
Expand Down
60 changes: 60 additions & 0 deletions skills/turbodocx-sdk/references/php.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,66 @@ $result = TurboSign::sendSignature(
echo "Document ID: {$result->documentId}\n";
```

### Conditional (IF/THEN) fields

Any field can be made to depend on a **controlling checkbox** so it only appears — or only becomes editable — once the signer ticks that box. Give the checkbox a stable `metadata` with a `fieldKey`, then reference that key from the dependent field's `metadata->conditional->controllingFieldKey`. The `metadata:` argument on `Field` is **optional**; a `Field` without it behaves exactly as before.

```php
use TurboDocx\TurboSign;
use TurboDocx\Types\Recipient;
use TurboDocx\Types\Field;
use TurboDocx\Types\SignatureFieldType;
use TurboDocx\Types\FieldMetadata;
use TurboDocx\Types\FieldConditional;
use TurboDocx\Types\ConditionalOperator;
use TurboDocx\Types\ConditionalAction;
use TurboDocx\Types\Requests\SendSignatureRequest;

$result = TurboSign::sendSignature(
new SendSignatureRequest(
file: file_get_contents('contract.pdf'),
documentName: 'Employment Agreement',
recipients: [
new Recipient('John Doe', 'john@example.com', 1),
],
fields: [
// Controlling checkbox — the box the signer ticks. Its fieldKey is the stable id others reference.
new Field(
type: SignatureFieldType::CHECKBOX,
recipientEmail: 'john@example.com',
page: 1,
x: 100,
y: 400,
width: 20,
height: 20,
metadata: new FieldMetadata(fieldKey: 'relocation_optin'),
),
// Dependent field — hidden until the box above is checked (action: "show").
new Field(
type: SignatureFieldType::SIGNATURE,
recipientEmail: 'john@example.com',
page: 1,
x: 100,
y: 460,
width: 200,
height: 50,
metadata: new FieldMetadata(
conditional: new FieldConditional(
controllingFieldKey: 'relocation_optin', // = the checkbox's metadata fieldKey
operator: ConditionalOperator::IS_CHECKED, // ::IS_CHECKED | ::IS_NOT_CHECKED
action: ConditionalAction::SHOW, // ::SHOW = hidden until met; ::UNLOCK = visible but read-only until met
),
),
),
],
)
);

echo "Document ID: {$result->documentId}\n";
```

The link is `fieldKey` → `controllingFieldKey`: the two strings must match exactly (the checkbox carries `metadata->fieldKey`, the dependent field points at it via `metadata->conditional->controllingFieldKey`). `operator` chooses which checkbox state satisfies the condition — `'is_checked'` or `'is_not_checked'`. `action` chooses what happens while the condition is unmet: `'show'` keeps the dependent field **hidden until met**, while `'unlock'` renders it **visible but read-only (locked) until met**.

### getStatus

```php
Expand Down
38 changes: 38 additions & 0 deletions skills/turbodocx-sdk/references/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,44 @@ result = await TurboSign.send_signature(
print(f"Document ID: {result['documentId']}")
```

### Conditional (IF/THEN) fields

Any field can be made to depend on a **controlling checkbox** so it only appears — or only becomes editable — once the signer ticks that box. Give the checkbox a stable `metadata["fieldKey"]`, then reference that key from the dependent field's `metadata["conditional"]["controllingFieldKey"]`. Both live in an **optional** `metadata` dict on the field; fields without it behave exactly as before. Note the keys inside `metadata` stay camelCase (`fieldKey`, `controllingFieldKey`) — they are forwarded to the API verbatim.

```python
result = await TurboSign.send_signature(
file=pdf_file,
document_name="Employment Agreement",
recipients=[
{"name": "John Doe", "email": "john@example.com", "signingOrder": 1},
],
fields=[
# Controlling checkbox — the box the signer ticks. Its metadata.fieldKey is the stable id others reference.
{
"type": "checkbox",
"page": 1, "x": 100, "y": 400, "width": 20, "height": 20,
"recipientEmail": "john@example.com",
"metadata": {"fieldKey": "relocation_optin"},
},
# Dependent field — hidden until the box above is checked (action: "show").
{
"type": "signature",
"page": 1, "x": 100, "y": 460, "width": 200, "height": 50,
"recipientEmail": "john@example.com",
"metadata": {
"conditional": {
"controllingFieldKey": "relocation_optin", # = the checkbox's metadata.fieldKey
"operator": "is_checked", # "is_checked" | "is_not_checked"
"action": "show", # "show" = hidden until met; "unlock" = visible but read-only until met
},
},
},
],
)
```

The link is `fieldKey` → `controllingFieldKey`: the two strings must match exactly (the checkbox carries `metadata["fieldKey"]`, the dependent field points at it via `metadata["conditional"]["controllingFieldKey"]`). `operator` chooses which checkbox state satisfies the condition — `is_checked` or `is_not_checked`. `action` chooses what happens while the condition is unmet: `show` keeps the dependent field **hidden until met**, while `unlock` renders it **visible but read-only (locked) until met**.

### get_status

```python
Expand Down
Loading