How to Upload Files to the Legalesign Platform
Many tasks require you to provide a file for the Legalesign platform to use, such as a file to use as a template or an image to use for a signature.
The platform requires you to place this file in the correct sub-folder of our clearing system. This will vet your file for possible security issues and pass it on to the correct location for its purpose.
What You'll Learn
This guide will walk you through uploading files to Legalesign. Don't worry if you're new to APIs or cloud storage - we'll explain each step clearly.
What is a Pre-Signed URL?
A pre-signed URL is like a temporary access pass. Instead of giving you permanent access to our storage, we give you a special URL that:
- Only works for a short time (15 minutes)
- Only allows you to upload one specific file
- Keeps your files secure
Think of it like a valet parking ticket - it gives temporary, limited access for a specific purpose.
What is S3?
S3 (Simple Storage Service) is Amazon's cloud file storage. It's where we safely store your documents, logos, and other files. You don't need to understand S3 in detail - just know that it's a secure place to store files in the cloud.
Overview
The upload process follows these steps:
- Request a pre-signed upload URL from the GraphQL API (ask for permission to upload)
- Upload your file to S3 using the provided URL (actually send the file)
- The platform automatically processes and validates the file (we check it's safe)
- The file is moved to its final destination (we put it in the right place)
Why This Two-Step Process?
You might wonder why we don't just let you upload directly. This two-step process:
- Ensures you have permission to upload
- Prevents unauthorized file uploads
- Allows us to scan files for viruses
- Keeps track of who uploaded what
Step 1: Request Upload URL
First, you need to ask Legalesign for permission to upload your file. You do this by sending a GraphQL query.
What is GraphQL?
GraphQL is a way to request data from an API. Think of it like filling out a form - you specify what you want, and the server responds with exactly that information.
Use the upload query to obtain a pre-signed URL for your file upload (in this case a PDF). See our authentication guide for more information on how to get started running GraphQL queries.
query {
upload(
id: "<BASE64_OBJECT_ID>",
uploadType: TEMPLATE,
extension: "pdf"
) {
url
}
}
Parameters Explained
-
id: Base64-encoded object ID (e.g., template ID, experience ID)
- This is a unique identifier for your template or document
- It looks like a random string of letters and numbers
- You'll get this ID when you create a template through the API
-
uploadType: The type of file being uploaded
- This tells us what you're uploading so we can process it correctly
- See upload types below
-
extension: File extension (pdf, png, jpg)
- This is the file type (the part after the dot in a filename)
- Examples: "pdf" for document.pdf, "png" for logo.png
Upload Types
TEMPLATE- PDF files for document templatesLOGO- Images for signing page brandingEMAILLOGO- Images for email brandingATTACHMENT- Additional files to attach to documents
Step 2: Upload to S3
Once you receive the pre-signed URL from Step 1, you can now upload your actual file.
How Does This Work?
The query returns a special URL (the pre-signed URL we mentioned earlier). You then send your file to this URL using an HTTP PUT request.
What is an HTTP PUT Request?
HTTP PUT is a method for sending data to a server. Think of it like:
- GET = asking for something ("Can I see that file?")
- PUT = giving something ("Here's my file, please store it")
Here's a simple example:
const response = await fetch(url, {
method: 'PUT',
body: fileData,
headers: {
'Content-Type': 'application/pdf' // or appropriate MIME type
}
});
Step 3: Automatic Processing
Once uploaded, the platform:
- Scans the file for viruses and security threats
- Validates the file format and content
- Processes the file (e.g., extracts page dimensions for PDFs)
- Moves it to the final storage location with appropriate permissions
Complete Example
Here's a complete working example in three popular programming languages. Each example does the same thing:
- Connects to the Legalesign API
- Requests permission to upload (gets the pre-signed URL)
- Uploads the file to S3
- Confirms success
Before You Start
You'll need:
- Your Legalesign account credentials (username and password)
- The file you want to upload
- The object ID (template ID or experience ID) where the file should be attached
Understanding the Code
Each example follows the same pattern:
- Import libraries: Load the tools we need
- Set up authentication: Prove who you are
- Get upload URL: Request permission to upload
- Upload file: Send the actual file
- Handle errors: Deal with problems if they occur
- JavaScript
- Python
- C#
import { generateClient } from 'aws-amplify/api';
const uploadFile = async (objectId, file) => {
const client = generateClient();
const extension = file.name.split('.').pop();
// Step 1: Get upload URL
const result = await client.graphql({
query: `
query {
upload(
id: "${objectId}",
uploadType: TEMPLATE,
extension: "${extension}"
) {
url
}
}
`
});
const uploadUrl = result.data.upload.url;
// Step 2: Upload file
const response = await fetch(uploadUrl, {
method: 'PUT',
body: file,
headers: {
'Content-Type': file.type
}
});
if (!response.ok) {
throw new Error('Upload failed');
}
return { success: true };
};
import requests
import base64
from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport
def upload_file(graphql_endpoint, auth_token, object_id, file_path):
# Get file extension
extension = file_path.split('.')[-1]
# Step 1: Get upload URL
transport = RequestsHTTPTransport(
url=graphql_endpoint,
headers={'Authorization': auth_token}
)
client = Client(transport=transport, fetch_schema_from_transport=True)
query = gql(f'''
query {{
upload(
id: "{object_id}",
uploadType: TEMPLATE,
extension: "{extension}"
) {{
url
}}
}}
''')
result = client.execute(query)
upload_url = result['upload']['url']
# Step 2: Upload file
with open(file_path, 'rb') as f:
file_data = f.read()
response = requests.put(
upload_url,
data=file_data,
headers={'Content-Type': 'application/pdf'}
)
if response.status_code != 200:
raise Exception('Upload failed')
return {'success': True}
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using GraphQL;
using GraphQL.Client.Http;
using GraphQL.Client.Serializer.Newtonsoft;
public class FileUploader
{
public async Task<bool> UploadFile(string graphqlEndpoint, string authToken,
string objectId, string filePath)
{
var extension = Path.GetExtension(filePath).TrimStart('.');
// Step 1: Get upload URL
var graphQLClient = new GraphQLHttpClient(
graphqlEndpoint,
new NewtonsoftJsonSerializer()
);
graphQLClient.HttpClient.DefaultRequestHeaders.Add("Authorization", authToken);
var query = new GraphQLRequest
{
Query = $@"
query {{
upload(
id: ""{objectId}"",
uploadType: TEMPLATE,
extension: ""{extension}""
) {{
url
}}
}}
"
};
var response = await graphQLClient.SendQueryAsync<dynamic>(query);
string uploadUrl = response.Data.upload.url;
// Step 2: Upload file
using var httpClient = new HttpClient();
var fileBytes = await File.ReadAllBytesAsync(filePath);
var content = new ByteArrayContent(fileBytes);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
var uploadResponse = await httpClient.PutAsync(uploadUrl, content);
if (!uploadResponse.IsSuccessStatusCode)
{
throw new Exception("Upload failed");
}
return true;
}
}
Path Format
Understanding File Paths
When files are stored, they follow a specific naming pattern. This helps organize files and ensures they go to the right place.
Files must follow this naming convention:
<uploadType>/<userId>/<base64ObjectId>.<extension>
Breaking Down the Path
- uploadType: What kind of file (template, logo, etc.)
- userId: Your unique user identifier (automatically added)
- base64ObjectId: The ID of the template or object (the "id" parameter from Step 1)
- extension: File type (pdf, png, jpg)
Real Example
Example:
template/usr123abc/dHBsYjQ5YTg5NWQtYWRhMy0xMWYwLWIxZGMtMDY5NzZlZmU0MzIx.pdf
This means:
- It's a template file
- Uploaded by user usr123abc
- For template ID dHBsYjQ5YTg5NWQtYWRhMy0xMWYwLWIxZGMtMDY5NzZlZmU0MzIx
- It's a PDF file
You don't need to create this path yourself - the API handles it automatically when you provide the correct parameters.
Supported File Types
Templates
- PDF files only
- Maximum size: 50MB
Logos and Email Logos
- PNG, JPG, JPEG
- Maximum size: 5MB
- Recommended dimensions: 200x200px (logos), 600x200px (email logos)
Attachments
- PDF, DOC, DOCX, XLS, XLSX, PNG, JPG
- Maximum size: 25MB
Error Handling
What Can Go Wrong?
Sometimes uploads fail. Here are the most common reasons and what they mean:
-
No permission: The object ID doesn't belong to your account or group
- What this means: You're trying to upload to a template you don't own
- How to fix: Check that you're using the correct object ID and that you have access to it
-
Invalid extension: File type not supported for this upload type
- What this means: You're trying to upload the wrong type of file (e.g., a Word doc as a template)
- How to fix: Convert your file to the correct format or use a different upload type
-
File too large: Exceeds maximum size limit
- What this means: Your file is bigger than we allow
- How to fix: Compress your file or reduce its size
-
Virus detected: File failed security scan
- What this means: Our security system found something suspicious in your file
- How to fix: Scan your file with antivirus software and try again with a clean file
Security Notes
How We Keep Your Files Safe
-
Pre-signed URLs expire after 15 minutes
- This means if someone intercepts your upload URL, they can't use it later
- If your upload takes longer than 15 minutes, you'll need to request a new URL
-
Files are scanned for viruses before processing
- Every file goes through security checks
- Infected files are rejected and never stored
-
Only users with appropriate permissions can upload files
- You can only upload to templates and objects you own or have access to
- This prevents unauthorized access to other users' data
-
Files are isolated during processing in the clearing bucket
- Uploaded files are kept separate until they pass all security checks
- Only after approval are they moved to permanent storage
Best Practices
- Always check file size before uploading - Save time by verifying your file meets size requirements
- Use the correct file format - Convert files to supported formats before uploading
- Handle errors gracefully - Always check for errors and provide helpful messages to users
- Don't reuse pre-signed URLs - Request a new URL for each upload
- Keep your credentials secure - Never share your authentication tokens or embed them in client-side code