Developer Guide

How to Sign PDFs with Go

3 steps to sign a PDF with Go: Install the TurboDocx SDK with go get github.com/TurboDocx/SDK/packages/go-sdk, create a client with turbodocx.NewClientWithConfig() using your API key and sender email, then call client.TurboSign.SendSignature() with a context, the PDF bytes, recipients, and signature fields to send it for e-signature.

This guide shows you how to integrate e-signatures into your Go application with idiomatic patterns and full context support in under 5 minutes.

Last updated: September 23, 2026

5 min

Setup time

Go

Go 1.21+

Zero dependencies

Context

Full support

1

Installation

Install the TurboDocx SDK using go get. The package has zero external dependencies.

Terminal
go get github.com/TurboDocx/SDK/packages/go-sdk

Requirements: Go 1.21+. The SDK is concurrent-safe and uses only the standard library.

2

Obtaining an API Key

Before you begin, you'll need your API credentials from the TurboDocx dashboard.

  1. Sign up for a free account at TurboDocx
  2. Navigate to Settings → API Keys
  3. Copy your API Key and Organization ID
.env or environment
export TURBODOCX_API_KEY=your_api_key_here
export TURBODOCX_ORG_ID=your_org_id_here
export TURBODOCX_SENDER_EMAIL=you@company.com
export TURBODOCX_SENDER_NAME="Your Company Name"
3

Sending a Signing Request

Use the SDK to send a document for signature. The recipient will receive an email with a link to sign.

main.go
package main

import (
    "context"
    "fmt"
    "log"
    "os"

    turbodocx "github.com/TurboDocx/SDK/packages/go-sdk"
)

func main() {
    // Create client with sender configuration
    client, err := turbodocx.NewClientWithConfig(turbodocx.ClientConfig{
        APIKey:      os.Getenv("TURBODOCX_API_KEY"),      // REQUIRED
        OrgID:       os.Getenv("TURBODOCX_ORG_ID"),       // REQUIRED
        SenderEmail: os.Getenv("TURBODOCX_SENDER_EMAIL"), // REQUIRED
        SenderName:  os.Getenv("TURBODOCX_SENDER_NAME"),  // Recommended
    })
    if err != nil {
        log.Fatal(err)
    }

    // Read PDF file
    pdfFile, err := os.ReadFile("contract.pdf")
    if err != nil {
        log.Fatal(err)
    }

    // Send document for signature
    result, err := client.TurboSign.SendSignature(context.Background(), &turbodocx.SendSignatureRequest{
        File:         pdfFile,
        FileName:     "contract.pdf",
        DocumentName: "Partnership Agreement",
        Recipients: []turbodocx.Recipient{
            {Name: "John Doe", Email: "john@example.com", SigningOrder: 1},
        },
        Fields: []turbodocx.Field{
            {
                Type:           "signature",
                RecipientEmail: "john@example.com",
                Template: &turbodocx.TemplateAnchor{
                    Anchor:    "{signature1}",
                    Placement: "replace",
                    Size:      &turbodocx.Size{Width: 100, Height: 30},
                },
            },
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Document ID: %s\n", result.DocumentID)
}

Tip: Always pass a context.Context for proper cancellation and timeout handling. To check status without a webhook, call client.TurboSign.GetStatus(ctx, result.DocumentID).

4

Processing Results with Webhooks

Configure webhooks to receive real-time notifications when documents are signed. Verify the X-TurboDocx-Signature header with turbodocx.VerifyWebhookSignature() against the raw request body before trusting a payload.

webhook_handler.go
func handleWebhook(w http.ResponseWriter, r *http.Request) {
    rawBody, err := io.ReadAll(r.Body)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    if !turbodocx.VerifyWebhookSignature(
        rawBody,
        r.Header.Get("X-TurboDocx-Signature"),
        r.Header.Get("X-TurboDocx-Timestamp"),
        os.Getenv("TURBODOCX_WEBHOOK_SECRET"),
        nil,
    ) {
        http.Error(w, "invalid signature", http.StatusUnauthorized)
        return
    }

    var payload struct {
        Event string `json:"event"`
        Data   struct {
            DocumentID string `json:"document_id"`
        } `json:"data"`
    }
    if err := json.Unmarshal(rawBody, &payload); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    if payload.Event == "signature.document.completed" {
        // Download the signed PDF
        signedPdf, err := client.TurboSign.Download(r.Context(), payload.Data.DocumentID)
        if err != nil {
            log.Printf("Download error: %v", err)
        }

        // Save to file
        os.WriteFile(fmt.Sprintf("signed-%s.pdf", payload.Data.DocumentID), signedPdf, 0644)
    }

    json.NewEncoder(w).Encode(map[string]bool{"received": true})
}
5

Conclusion

You now have everything you need to integrate document signing into your Go application using the TurboDocx e-signature API. It handles authentication, document delivery, signature collection, and legally-binding audit trails, all through the same context-aware Go client.

What you can do next:

  • Add multiple recipients with sequential signing order
  • Use different field types: initials, dates, text, checkboxes
  • Implement graceful shutdown with context cancellation
  • Get audit trails and compliance certificates

Related Guides

Resources

Frequently Asked Questions

How do I sign a PDF with Go?

Install the TurboDocx SDK (go get github.com/TurboDocx/SDK/packages/go-sdk), create a client with your API key, then use client.TurboSign.SendSignature() to send the document for e-signature.

Does the Go SDK support context.Context?

Yes, the TurboDocx Go SDK fully supports context.Context for cancellation, timeouts, and deadline propagation on every call.

What Go version is required?

The TurboDocx Go SDK requires Go 1.21 or higher. The library code has zero non-standard-library dependencies; testify is listed only as a test dependency.

Ready to Get Started?

Create a free account and get your API key. Start sending documents for signature in minutes.