File Uploads Guide¶
Step-by-step guide to upload PDF files to envelopes.
When to Use This¶
Use file uploads when your PDF files are larger than 1MB. For smaller files, use the standard base64 envelope creation method.
Quick Start¶
Step 1: Create Envelope (No Documents)¶
curl -X POST https://api.lexgo.cl/api/v1/envelopes \
-H "Authorization: YOUR_API_KEY" \
-F "name=Contract - John Doe" \
-F "recipients[0][name]=John Doe" \
-F "recipients[0][email]=john@example.com" \
-F "recipients[0][order]=1"
Save the envelope.id from the response.
Step 2: Request Upload URL¶
curl -X POST https://api.lexgo.cl/api/v1/envelopes/ENVELOPE_ID/uploads \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"file_name": "contract.pdf",
"order": 0
}'
Save the upload.upload_url and upload.id.
Step 3: Upload File¶
curl -X PUT "UPLOAD_URL" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/pdf" \
--data-binary @contract.pdf
Step 4: Wait for Processing¶
Option A: Poll for completion
curl https://api.lexgo.cl/api/v1/envelopes/ENVELOPE_ID/uploads/UPLOAD_ID \
-H "Authorization: YOUR_API_KEY"
Check upload.status in response. Repeat every 2 seconds until COMPLETED.
Option B: Use webhook (recommended for production)
Subscribe to envelope.file_uploaded event:
curl -X POST https://api.lexgo.cl/api/v1/webhooks \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/lexgo",
"subscriptions": "envelope.file_uploaded"
}'
Your webhook will receive notification when file is ready (no polling needed).
Step 5: Verify Documents Attached¶
Check the response:
- envelope.documents array contains your file
- envelope.errors is empty
- Each document has status: "READY"
Step 6: Send Envelope¶
curl -X POST https://api.lexgo.cl/api/v1/envelopes/ENVELOPE_ID/send_invitation \
-H "Authorization: YOUR_API_KEY"
Complete Working Script¶
Save this as upload_contract.sh:
#!/bin/bash
set -e
# Configuration
API_BASE="https://api.lexgo.cl/api/v1"
API_KEY="YOUR_API_KEY"
PDF_FILE="$1"
if [ -z "$PDF_FILE" ]; then
echo "Usage: $0 <pdf_file>"
exit 1
fi
if [ ! -f "$PDF_FILE" ]; then
echo "Error: File not found: $PDF_FILE"
exit 1
fi
echo "=== Step 1: Create Envelope ==="
ENVELOPE_JSON=$(curl -s -X POST "${API_BASE}/envelopes" \
-H "Authorization: ${API_KEY}" \
-F "name=Contract - Test" \
-F "recipients[0][name]=John Doe" \
-F "recipients[0][email]=john@example.com" \
-F "recipients[0][order]=1")
ENVELOPE_ID=$(echo "$ENVELOPE_JSON" | jq -r '.envelope.id')
if [ "$ENVELOPE_ID" = "null" ]; then
echo "Error creating envelope:"
echo "$ENVELOPE_JSON" | jq '.'
exit 1
fi
echo "✓ Created envelope: $ENVELOPE_ID"
echo ""
echo "=== Step 2: Request Upload URL ==="
UPLOAD_JSON=$(curl -s -X POST "${API_BASE}/envelopes/${ENVELOPE_ID}/uploads" \
-H "Authorization: ${API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"file_name\": \"$(basename "$PDF_FILE")\",
\"order\": 0
}")
UPLOAD_URL=$(echo "$UPLOAD_JSON" | jq -r '.upload.upload_url')
UPLOAD_ID=$(echo "$UPLOAD_JSON" | jq -r '.upload.id')
if [ "$UPLOAD_URL" = "null" ]; then
echo "Error requesting upload URL:"
echo "$UPLOAD_JSON" | jq '.'
exit 1
fi
echo "✓ Got upload URL"
echo "✓ Upload ID: $UPLOAD_ID"
echo ""
echo "=== Step 3: Upload File ==="
UPLOAD_RESPONSE=$(curl -s -X PUT "$UPLOAD_URL" \
-H "Authorization: ${API_KEY}" \
-H "Content-Type: application/pdf" \
--data-binary @"$PDF_FILE")
SUCCESS=$(echo "$UPLOAD_RESPONSE" | jq -r '.success')
if [ "$SUCCESS" != "true" ]; then
echo "Error uploading file:"
echo "$UPLOAD_RESPONSE" | jq '.'
exit 1
fi
echo "✓ Uploaded file"
echo ""
echo "=== Step 4: Wait for Processing ==="
MAX_ATTEMPTS=30
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
STATUS_JSON=$(curl -s "${API_BASE}/envelopes/${ENVELOPE_ID}/uploads/${UPLOAD_ID}" \
-H "Authorization: ${API_KEY}")
STATUS=$(echo "$STATUS_JSON" | jq -r '.upload.status')
echo " Status: $STATUS (attempt $((ATTEMPT+1))/$MAX_ATTEMPTS)"
if [ "$STATUS" = "COMPLETED" ]; then
FILE_ID=$(echo "$STATUS_JSON" | jq -r '.upload.file_id')
echo "✓ File processed successfully!"
echo "✓ File ID: $FILE_ID"
break
elif [ "$STATUS" = "FAILED" ]; then
ERROR=$(echo "$STATUS_JSON" | jq -r '.upload.error_message')
echo "✗ Processing failed: $ERROR"
exit 1
fi
ATTEMPT=$((ATTEMPT+1))
sleep 2
done
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
echo "✗ Timeout waiting for processing"
exit 1
fi
echo ""
echo "=== Step 5: Verify Envelope ==="
ENVELOPE_JSON=$(curl -s "${API_BASE}/envelopes/${ENVELOPE_ID}" \
-H "Authorization: ${API_KEY}")
DOC_COUNT=$(echo "$ENVELOPE_JSON" | jq '.envelope.documents | length')
ERRORS=$(echo "$ENVELOPE_JSON" | jq '.envelope.errors | length')
if [ "$DOC_COUNT" -eq 0 ]; then
echo "✗ No documents attached to envelope"
exit 1
fi
if [ "$ERRORS" -gt 0 ]; then
echo "✗ Envelope has errors:"
echo "$ENVELOPE_JSON" | jq '.envelope.errors'
exit 1
fi
echo "✓ Envelope verified: $DOC_COUNT document(s), no errors"
echo ""
echo "=== Step 6: Send Envelope ==="
SEND_JSON=$(curl -s -X POST "${API_BASE}/envelopes/${ENVELOPE_ID}/send_invitation" \
-H "Authorization: ${API_KEY}")
SUCCESS=$(echo "$SEND_JSON" | jq -r '.success')
if [ "$SUCCESS" = "true" ]; then
echo "✓ Envelope sent!"
echo ""
echo "Done! Envelope ID: $ENVELOPE_ID"
else
echo "✗ Failed to send envelope:"
echo "$SEND_JSON" | jq '.'
exit 1
fi
Make it executable and run:
Python Implementation¶
Save as upload_contract.py:
#!/usr/bin/env python3
import requests
import time
import sys
import os
API_BASE = "https://api.lexgo.cl/api/v1"
API_KEY = "YOUR_API_KEY"
def create_envelope():
print("=== Step 1: Create Envelope ===")
response = requests.post(
f"{API_BASE}/envelopes",
headers={"Authorization": API_KEY},
data={
"name": "Contract - Test",
"recipients[0][name]": "John Doe",
"recipients[0][email]": "john@example.com",
"recipients[0][order]": "1"
}
)
response.raise_for_status()
envelope_id = response.json()["envelope"]["id"]
print(f"✓ Created envelope: {envelope_id}")
return envelope_id
def request_upload_url(envelope_id, filename):
print("\n=== Step 2: Request Upload URL ===")
response = requests.post(
f"{API_BASE}/envelopes/{envelope_id}/uploads",
headers={
"Authorization": API_KEY,
"Content-Type": "application/json"
},
json={
"file_name": os.path.basename(filename),
"order": 0
}
)
response.raise_for_status()
data = response.json()["upload"]
print("✓ Got upload URL")
print(f"✓ Upload ID: {data['id']}")
return data["upload_url"], data["id"]
def upload_file(upload_url, pdf_path):
print("\n=== Step 3: Upload File ===")
with open(pdf_path, "rb") as f:
response = requests.put(
upload_url,
data=f,
headers={
"Authorization": API_KEY,
"Content-Type": "application/pdf"
}
)
response.raise_for_status()
print("✓ Uploaded file")
def wait_for_processing(envelope_id, upload_id):
print("\n=== Step 4: Wait for Processing ===")
max_attempts = 30
for attempt in range(max_attempts):
response = requests.get(
f"{API_BASE}/envelopes/{envelope_id}/uploads/{upload_id}",
headers={"Authorization": API_KEY}
)
response.raise_for_status()
upload = response.json()["upload"]
status = upload["status"]
print(f" Status: {status} (attempt {attempt+1}/{max_attempts})")
if status == "COMPLETED":
print("✓ File processed successfully!")
print(f"✓ File ID: {upload['file_id']}")
return True
elif status == "FAILED":
print(f"✗ Processing failed: {upload.get('error_message', 'Unknown error')}")
return False
time.sleep(2)
print("✗ Timeout waiting for processing")
return False
def verify_envelope(envelope_id):
print("\n=== Step 5: Verify Envelope ===")
response = requests.get(
f"{API_BASE}/envelopes/{envelope_id}",
headers={"Authorization": API_KEY}
)
response.raise_for_status()
envelope = response.json()["envelope"]
doc_count = len(envelope["documents"])
error_count = len(envelope.get("errors", []))
if doc_count == 0:
print("✗ No documents attached to envelope")
return False
if error_count > 0:
print(f"✗ Envelope has {error_count} error(s)")
return False
print(f"✓ Envelope verified: {doc_count} document(s), no errors")
return True
def send_envelope(envelope_id):
print("\n=== Step 6: Send Envelope ===")
response = requests.post(
f"{API_BASE}/envelopes/{envelope_id}/send_invitation",
headers={"Authorization": API_KEY}
)
response.raise_for_status()
if response.json()["success"]:
print("✓ Envelope sent!")
return True
else:
print("✗ Failed to send envelope")
return False
def main():
if len(sys.argv) != 2:
print("Usage: python upload_contract.py <pdf_file>")
sys.exit(1)
pdf_path = sys.argv[1]
try:
envelope_id = create_envelope()
upload_url, upload_id = request_upload_url(envelope_id, pdf_path)
upload_file(upload_url, pdf_path)
if not wait_for_processing(envelope_id, upload_id):
sys.exit(1)
if not verify_envelope(envelope_id):
sys.exit(1)
if not send_envelope(envelope_id):
sys.exit(1)
print(f"\nDone! Envelope ID: {envelope_id}")
except requests.HTTPError as e:
print(f"\n✗ API Error: {e.response.status_code}")
print(e.response.json())
sys.exit(1)
except Exception as e:
print(f"\n✗ Error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
Run it:
Common Issues¶
"URL expired" (403 error)¶
Fix: Request a new upload URL. They expire after 1 hour.
Status stuck in PENDING¶
Fix: Verify the upload succeeded (should return 200 with success: true).
Status changes to FAILED¶
Fix: Check the error message and validate your PDF.
# Get error details
curl https://api.lexgo.cl/api/v1/envelopes/$ENVELOPE_ID/uploads/$UPLOAD_ID \
-H "Authorization: YOUR_API_KEY" | jq '.upload.error_message'
# Common errors:
# - "Invalid PDF format" -> corrupted file
# - "Encrypted PDF" -> remove password
# - "File too large" -> must be <50MB
Cannot create upload (422 error)¶
Fix: Another upload for this order already exists.
# Check existing uploads
curl https://api.lexgo.cl/api/v1/envelopes/$ENVELOPE_ID/uploads \
-H "Authorization: YOUR_API_KEY" | jq '.uploads[] | select(.order == 0)'
# Wait for completion or use different order number
Next Steps¶
- File Upload API Reference - Complete API documentation
- Envelopes API - Standard base64 upload method
- Quick Start Guide - Getting started with the API