Documentation

AWS Cloud Connector API Reference

Endpoints, request shape, and process flow for sealing PDFs through the Trusted Signatures AWS Cloud Connector.

  • S3 source and destination flow
  • Lambda invocation
  • Digest-only sealing request

AWS proof

Use Lambda and S3 for connector speed, scale, and account-scoped control

The documented AWS pattern uses Lambda for invocation, S3 for document movement, and AWS-native IAM and secrets controls so teams can run sealing workflows inside their own account.

Trust & Standards

S3

speed path

Source and destination buckets let applications hand off PDFs and retrieve sealed output through the same storage workflow.

Lambda

scale model

The connector runs as a Lambda function, fitting bursty or event-driven document jobs without managing long-lived servers.

IAM

security controls

Least-privilege roles, bucket policies, and Secrets Manager guidance scope access to documents and credentials.

SHA-256

data boundary

Only the document digest and signing metadata are sent to Trusted Signatures while PDFs stay in S3.

API Reference

The Trusted Signatures AWS Cloud Connector provides businesses with a scalable, cost-effective API in their own infrastructure to seal even the most sensitive documents. By deploying the connector in their own AWS account, customers have assurance that none of the information in the documents can be intercepted or modified. Only an SHA-256 digest of the PDF is sent to Trusted Signatures for signing; no other data about the document exits the customer’s infrastructure.

The AWS Cloud Connector is deployed as a Lambda function. Customers put the PDFs that they wish to seal into an S3 bucket, invoke the Lambda function, and receive the sealed PDF back in a destination bucket.

Architecture Overview

Process Flow

Access Methods

Complete Workflow:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const AWS = require("aws-sdk");
const s3 = new AWS.S3();
const lambda = new AWS.Lambda();

// 1. Upload PDF to S3
await s3
  .putObject({
    Bucket: "source-bucket",
    Key: "input.pdf",
    Body: pdfBuffer,
  })
  .promise();

// 2. Invoke Lambda
const result = await lambda
  .invoke({
    FunctionName: "pdf-sealer-gateway",
    Payload: JSON.stringify({
      httpMethod: "POST",
      path: "/seal",
      body: JSON.stringify({
        sourceBucket: "source-bucket",
        sourceKey: "input.pdf",
        destinationBucket: "dest-bucket",
        destinationKey: "sealed.pdf",
        apiKey: "hex-key",
        apiKeyId: "key-id",
        tsaTimestamp: true,
        includeLtv: true,
      }),
    }),
  })
  .promise();

// 3. Download sealed PDF from S3
const sealedPdf = await s3
  .getObject({
    Bucket: "dest-bucket",
    Key: "sealed.pdf",
  })
  .promise();

// 4. Delete PDFs from S3 (optional - or use S3 lifecycle policies)
await s3
  .deleteObject({
    Bucket: "source-bucket",
    Key: "input.pdf",
  })
  .promise();

await s3
  .deleteObject({
    Bucket: "dest-bucket",
    Key: "sealed.pdf",
  })
  .promise();

API Gateway (Optional): If you create API Gateway:

1
https://your-api-id.execute-api.region.amazonaws.com

Authentication

Trusted Signatures API Keys

Gateway Access Control

You are responsible for securing the API endpoint that fronts the AWS Cloud Connector. Options:

Direct Lambda Invocation (Most Secure):

  • Use AWS SDK to invoke Lambda directly
  • Control access with IAM policies
  • No public HTTP endpoint

API Gateway (Optional):

  • You may create API Gateway if needed
  • Must limit access if you create one
  • Configure proper authentication and authorization

Endpoints

Health Check

Verify the Lambda function is operational.

1
GET /health

Response:

1
2
3
{
  "status": "ok"
}

Seal PDF Document

Digitally seal a PDF document with Trusted Signatures using S3 storage.

1
2
POST /seal
Content-Type: application/json

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "sourceBucket": "your-source-bucket",
  "sourceKey": "path/to/document.pdf",
  "destinationBucket": "your-destination-bucket",
  "destinationKey": "path/to/sealed-document.pdf",
  "apiKey": "<hex-encoded-api-key>",
  "apiKeyId": "your-api-key-id",
  "tsaTimestamp": true,
  "includeLtv": true,
  "limitChanges": "no-changes"
}

Parameters:

FieldTypeRequiredDescription
sourceBucketstringYesS3 bucket containing source PDF
sourceKeystringYesS3 key (path) to source PDF
destinationBucketstringYesS3 bucket for sealed PDF
destinationKeystringYesS3 key (path) for sealed PDF
apiKeystringYesHex-encoded API key from Trusted Signatures
apiKeyIdstringYesYour API key identifier
tsaTimestampbooleanYesInclude timestamp authority signature
includeLtvbooleanYesInclude Long Term Validation data
limitChangesstringNoPDF modification restrictions

Important:

  • Use unique sourceKey and destinationKey values for concurrent invocations to avoid conflicts
  • The Gateway will not delete the source PDF from the source bucket after processing
  • The source and destination buckets may be the same, or different buckets

limitChanges Options:

  • "no-changes" - No modifications allowed (default)
  • "allow-forms" - Allow form filling only
  • "allow-comments" - Allow comments and annotations

Response:

1
2
3
4
5
6
{
  "sealedPdfLocation": {
    "bucket": "your-destination-bucket",
    "key": "path/to/sealed-document.pdf"
  }
}

Status Codes:

  • 200 - Success
  • 400 - Invalid request
  • 500 - Server error

Usage Examples

JavaScript/Node.js with S3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
const AWS = require("aws-sdk");
const s3 = new AWS.S3();
const lambda = new AWS.Lambda();

async function sealPdf() {
  // Upload PDF to S3 first
  const fs = require("fs");
  const pdfBuffer = fs.readFileSync("document.pdf");

  const sourceBucket = "your-source-bucket";
  const sourceKey = "uploads/document.pdf";
  const destinationBucket = "your-destination-bucket";
  const destinationKey = "sealed/sealed-document.pdf";

  // Upload to S3
  await s3
    .putObject({
      Bucket: sourceBucket,
      Key: sourceKey,
      Body: pdfBuffer,
      ContentType: "application/pdf",
    })
    .promise();

  // Invoke Lambda
  const result = await lambda
    .invoke({
      FunctionName: "pdf-sealer-gateway",
      Payload: JSON.stringify({
        httpMethod: "POST",
        path: "/seal",
        body: JSON.stringify({
          sourceBucket: sourceBucket,
          sourceKey: sourceKey,
          destinationBucket: destinationBucket,
          destinationKey: destinationKey,
          apiKey: "your-hex-api-key",
          apiKeyId: "your-key-id",
          tsaTimestamp: true,
          includeLtv: true,
          limitChanges: "no-changes",
        }),
      }),
    })
    .promise();

  const response = JSON.parse(result.Payload);
  if (response.statusCode === 200) {
    const body = JSON.parse(response.body);
    console.log("PDF sealed successfully!");
    console.log("Sealed PDF location:", body.sealedPdfLocation);

    // Download sealed PDF
    const sealedPdf = await s3
      .getObject({
        Bucket: body.sealedPdfLocation.bucket,
        Key: body.sealedPdfLocation.key,
      })
      .promise();

    fs.writeFileSync("sealed-document.pdf", sealedPdf.Body);

    // Delete PDFs from S3 (optional - or use S3 lifecycle policies)
    await s3
      .deleteObject({
        Bucket: sourceBucket,
        Key: sourceKey,
      })
      .promise();

    await s3
      .deleteObject({
        Bucket: destinationBucket,
        Key: destinationKey,
      })
      .promise();
  } else {
    throw new Error(`Sealing failed: ${response.body}`);
  }
}

sealPdf().catch(console.error);

Python with S3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import boto3

def seal_pdf():
    s3 = boto3.client('s3')
    lambda_client = boto3.client('lambda')

    source_bucket = 'your-source-bucket'
    source_key = 'uploads/document.pdf'
    dest_bucket = 'your-destination-bucket'
    dest_key = 'sealed/sealed-document.pdf'

    # Upload PDF to S3
    with open('document.pdf', 'rb') as f:
        s3.put_object(
            Bucket=source_bucket,
            Key=source_key,
            Body=f.read(),
            ContentType='application/pdf'
        )

    # Invoke Lambda
    response = lambda_client.invoke(
        FunctionName='pdf-sealer-gateway',
        Payload=json.dumps({
            'httpMethod': 'POST',
            'path': '/seal',
            'body': json.dumps({
                'sourceBucket': source_bucket,
                'sourceKey': source_key,
                'destinationBucket': dest_bucket,
                'destinationKey': dest_key,
                'apiKey': 'your-hex-api-key',
                'apiKeyId': 'your-key-id',
                'tsaTimestamp': True,
                'includeLtv': True,
                'limitChanges': 'no-changes'
            })
        })
    )

    # Download sealed PDF
    sealed_obj = s3.get_object(Bucket=dest_bucket, Key=dest_key)
    with open('sealed-document.pdf', 'wb') as f:
        f.write(sealed_obj['Body'].read())

    # Delete PDFs from S3 (optional - or use S3 lifecycle policies)
    s3.delete_object(Bucket=source_bucket, Key=source_key)
    s3.delete_object(Bucket=dest_bucket, Key=dest_key)

    print('PDF sealed successfully!')

if __name__ == '__main__':
    seal_pdf()

AWS CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Upload PDF to S3
aws s3 cp document.pdf s3://your-source-bucket/uploads/document.pdf

# Invoke Lambda
aws lambda invoke \
  --function-name pdf-sealer-gateway \
  --payload '{
    "httpMethod": "POST",
    "path": "/seal",
    "body": "{
      \"sourceBucket\": \"your-source-bucket\",
      \"sourceKey\": \"uploads/document.pdf\",
      \"destinationBucket\": \"your-destination-bucket\",
      \"destinationKey\": \"sealed/sealed-document.pdf\",
      \"apiKey\": \"your-hex-api-key\",
      \"apiKeyId\": \"your-key-id\",
      \"tsaTimestamp\": true,
      \"includeLtv\": true,
      \"limitChanges\": \"no-changes\"
    }"
  }' response.json

# Download sealed PDF
aws s3 cp s3://your-destination-bucket/sealed/sealed-document.pdf sealed-document.pdf

# Delete PDFs from S3 (optional - or use S3 lifecycle policies)
aws s3 rm s3://your-source-bucket/uploads/document.pdf
aws s3 rm s3://your-destination-bucket/sealed/sealed-document.pdf

PHP with AWS SDK

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<?php
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Lambda\LambdaClient;

function sealPdf() {
    $s3 = new S3Client(['region' => 'us-east-1']);
    $lambda = new LambdaClient(['region' => 'us-east-1']);

    $sourceBucket = 'your-source-bucket';
    $sourceKey = 'uploads/document.pdf';
    $destBucket = 'your-destination-bucket';
    $destKey = 'sealed/sealed-document.pdf';

    // Upload PDF to S3
    $s3->putObject([
        'Bucket' => $sourceBucket,
        'Key' => $sourceKey,
        'Body' => file_get_contents('document.pdf'),
        'ContentType' => 'application/pdf'
    ]);

    // Invoke Lambda
    $result = $lambda->invoke([
        'FunctionName' => 'pdf-sealer-gateway',
        'Payload' => json_encode([
            'httpMethod' => 'POST',
            'path' => '/seal',
            'body' => json_encode([
                'sourceBucket' => $sourceBucket,
                'sourceKey' => $sourceKey,
                'destinationBucket' => $destBucket,
                'destinationKey' => $destKey,
                'apiKey' => 'your-hex-api-key',
                'apiKeyId' => 'your-key-id',
                'tsaTimestamp' => true,
                'includeLtv' => true,
                'limitChanges' => 'no-changes'
            ])
        ])
    ]);

    // Download sealed PDF
    $sealedObj = $s3->getObject([
        'Bucket' => $destBucket,
        'Key' => $destKey
    ]);
    file_put_contents('sealed-document.pdf', $sealedObj['Body']);

    // Delete PDFs from S3 (optional - or use S3 lifecycle policies)
    $s3->deleteObject(['Bucket' => $sourceBucket, 'Key' => $sourceKey]);
    $s3->deleteObject(['Bucket' => $destBucket, 'Key' => $destKey]);

    echo "PDF sealed successfully!\n";
}

sealPdf();
?>
```nfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode !== 200) {
        throw new Exception("HTTP $httpCode: $response");
    }

    $result = json_decode($response, true);
    return base64_decode($result['sealedPdf']);
}

// Usage
try {
    $sealedPdf = sealPdf(
        'document.pdf',
        'your-hex-api-key',
        'your-key-id',
        'https://your-api-gateway-url'
    );

    file_put_contents('sealed-document.pdf', $sealedPdf);
    echo "PDF sealed successfully!\n";
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
?>

Error Handling

400 Bad Request

Missing or invalid parameters:

1
2
3
{
  "error": "Missing required fields: sourceBucket, sourceKey, destinationBucket, destinationKey, apiKey, apiKeyId, tsaTimestamp, includeLtv"
}

403 Forbidden

Insufficient S3 permissions:

1
2
3
{
  "error": "Access denied to source: s3://bucket/key. Check Lambda IAM permissions."
}
1
2
3
{
  "error": "Access denied to destination: s3://bucket/key. Check Lambda IAM permissions."
}

404 Not Found

S3 resource not found:

1
2
3
{
  "error": "Source PDF not found: s3://bucket/key"
}
1
2
3
{
  "error": "Source bucket not found: bucket-name"
}
1
2
3
{
  "error": "Destination bucket not found: bucket-name"
}

500 Internal Server Error

Sealing operation failed:

1
2
3
{
  "error": "Sealing operation failed: Invalid API credentials"
}

Common causes:

  • Invalid API key or credentials
  • Malformed PDF document
  • Network connectivity issues
  • Trusted Signatures API unavailable
  • S3 service errors

Rate Limits

Default API Gateway limits:

  • 10,000 requests per second
  • 5,000 burst capacity

Configure throttling in API Gateway for your specific needs.

Best Practices

Security

  • You are responsible for securing the AWS Cloud Connector entry point
  • Use IAM-based, least-privilege approach
  • CRITICAL: Clients should store Trusted Signatures API credentials in AWS Secrets Manager
    • Never hardcode API keys in client applications or environment variables
    • Use IAM roles to grant client applications access to secrets
    • Rotate API keys regularly using Secrets Manager
    • The Lambda Gateway receives API keys in each request - it doesn’t need Secrets Manager access
  • Consider VPC deployment for enhanced security
  • Monitor for unusual usage patterns
  • Only SHA-256 digest transmitted to Trusted Signatures (PDFs stay in your environment)

Performance

  • Memory allocation must match PDF size - Lambda processes PDFs in memory
  • Rule of thumb: PDF size × 4 = minimum Lambda memory needed
  • For 100 MB PDF: allocate at least 400 MB Lambda memory (use 512 MB)
  • For 500 MB PDF: allocate at least 2 GB Lambda memory
  • Implement client-side retry logic
  • No PDF size limit (uses S3 for storage)
  • Consider Lambda timeout for very large PDFs (max 15 minutes)
  • Use S3 Transfer Acceleration for faster uploads if needed

Error Handling

  • Implement proper error handling in your code
  • Log errors for debugging
  • Set up monitoring and alerts

Support

For technical support:

Licensing

This API requires a valid Trusted Signatures Container Gateway license.

Need architectural review?

Book a technical walkthrough

For enterprise rollout, we can review trust model, controls, and integration patterns with your team.