Fileforge is shutting down on December, 25th, 2024. Get help migrating

Migrating from Fileforge

Wednesday, September 25, 2024

After 7 months of helping hundreds of businesses streamline their document workflows, we’ve made the difficult decision to discontinue Fileforge’s services as of December 25th, 2024. We understand this change may cause disruptions to your processes, and we’re committed to supporting you in making this transition as smooth as possible.

Why are we shutting down?

Fileforge was born from a mission to simplify document generation for businesses and individuals alike. Over the past 7 months, we’ve been proud to help hundreds of users create beautiful documents—from invoices to reports and everything in between. However, as the founding team moves in different directions, we’ve made the tough decision to wind down operations rather than pass the service onto a third party.

How will the migration happen?

All existing customers are welcome to book a hands-on migration session over the next week, where we will help with migrating your documents to other services.

You can book a session on my calendar.

Services will continue working until December 25th 2024.

Documents that are hosted on Fileforge will be available for download until December 25th 2024. Documents created from now on will have a maximum retention period capped to December 25th 2024.

Migration guide

We recommend that you use our migration chat to help you migrate your processes. You can also check the below guide for more information, and reach out to us if you need any help.

Methods:

Using the Migration Chat

We have set up an AI chatbot to help you migrate your processes. You can paste your existing code implementation and the chatbot will guide you through the migration process. The chatbot has knowledge of Fileforge, it’s API, most common use cases, as well as the recommended alternatives.

Migration Chat (interactive):

HTML to PDF

Our open-source library @fileforge/react-print will continue to work after the shutdown, although it will be archived and no longer maintained. You can still use it to generate HTML bundles to use with other services.

The DocRaptor API should provide a seamless transition for those who need a hosted solution, and we recommend it for its ease of use and reliability.

Those who would rather use a self-hosted solution can look into PrinceXML which will also provide a seamless transition.

Other renderers such as Puppeteer or wkhtmltopdf can also be used to generate PDFs from HTML, although most of the React-Print layout features will not be available.

Python Sample

1
# ----------------------------
2
# Fileforge API
3
# ----------------------------
4
5
import requests
6
7
headers = {
8
'accept': 'application/pdf',
9
'X-API-Key': 'blabla',
10
}
11
12
files = {
13
'options': (None, '{"test":true,"host":false,"expiresAt":"2024-09-25T10:24:58.927Z","fileName":"document","allowViewing":false}', 'application/json'),
14
'files': ('index.html', open('index.html', 'rb'), 'text/html'),
15
}
16
17
response = requests.post('https://api.fileforge.com/pdf/generate/', headers=headers, files=files)
18
19
# ----------------------------
20
# DocRaptor API
21
# ----------------------------
22
23
import docraptor
24
25
doc_api = docraptor.DocApi()
26
# this key works in test mode!
27
doc_api.api_client.configuration.username = 'YOUR_API_KEY_HERE'
28
29
try:
30
response = doc_api.create_doc({
31
'test': True, # test documents are free but watermarked
32
'document_type': 'pdf',
33
'document_content': open('index.html', 'rb'),
34
'prince_options': {
35
'media': 'print'
36
},
37
})
38
39
# create_doc() returns a binary string
40
with open('docraptor-hello.pdf', 'w+b') as f:
41
binary_formatted_response = bytearray(response)
42
f.write(binary_formatted_response)
43
f.close()
44
print('Successfully created docraptor-hello.pdf!')
45
except docraptor.rest.ApiException as error:
46
print(error.status)
47
print(error.reason)
48
print(error.body)

Javascript Sample

1
// ----------------------------
2
// Fileforge API
3
// ----------------------------
4
5
import { FileforgeClient } from "@fileforge/client";
6
7
const ff = new FileforgeClient({
8
apiKey: "xxx",
9
});
10
11
const html = await compile(<Document />);
12
13
const file = await ff.pdf.generate(
14
[
15
new File([html], "index.html", {
16
type: "text/html",
17
}),
18
],
19
{
20
options: {
21
host: false,
22
test: false,
23
allowViewing: true,
24
},
25
}
26
);
27
28
// ----------------------------
29
// DocRaptor API
30
// ----------------------------
31
32
const html = await compile(<Document />);
33
34
const response = await fetch("https://docraptor.com/docs", {
35
method: "POST",
36
headers: {
37
"Content-Type": "application/json",
38
Authorization: "xxx",
39
},
40
body: JSON.stringify({
41
test: true,
42
document_content: html,
43
document_type: "pdf",
44
}),
45
});
46
47
const blob = await response.blob();

DOCX to PDF, Merging, Splitting and Forms Operations

For other operations, we recommend using PDF.co which provides a wide range of operations on PDFs, including merging, splitting, and form filling. You can buy prepaid credits to use the service, or you can subscribe to a monthly plan.

Operations Table

We have selected PDF.co as the recommended alternative for the following operations:

OperationFileforge APIPDF.co
DOCX to PDF/pdf/docx/Yes, without templated variables
PDF Form Fields Identification/pdf/form/detect/Yes
Visual PDF Form Fields Identification/pdf/form/mark/No
PDF Form Fields Filling/pdf/form/fill/Yes
PDF Merge/pdf/merge/Yes
PDF Split/pdf/split/Yes

Specifics

File Upload

PDF.co works with URLs rather than files in its API. You can upload raw files via POST or via presigned URLs to PDF.co’s storage and then use them in your operations. You can also upload files by URL, for example to download a file using a presigned URL from your cloud storage.

Samples
Merging two PDF Files

Use PDF.co’s API to merge two PDF files. First, we upload the two PDF files, then we merge them, and finally, we download the merged PDF.

1
import requests
2
3
# Replace with your actual PDF.co API key
4
API_KEY = 'YOUR_PDF_CO_API_KEY'
5
6
try:
7
# Upload first PDF file
8
upload_url = 'https://api.pdf.co/v1/file/upload/get-presigned-url'
9
headers = {'x-api-key': API_KEY}
10
payload = {'name': 'file1.pdf'}
11
12
response = requests.post(upload_url, json=payload, headers=headers)
13
if response.status_code != 200:
14
raise Exception(f"File 1 upload failed: {response.text}")
15
16
upload_data = response.json()
17
with open('path/to/your/first/file.pdf', 'rb') as file:
18
requests.put(upload_data['presignedUrl'], data=file)
19
file1_url = upload_data['url']
20
print("File 1 uploaded successfully.")
21
22
# Upload second PDF file
23
payload = {'name': 'file2.pdf'}
24
25
response = requests.post(upload_url, json=payload, headers=headers)
26
if response.status_code != 200:
27
raise Exception(f"File 2 upload failed: {response.text}")
28
29
upload_data = response.json()
30
with open('path/to/your/second/file.pdf', 'rb') as file:
31
requests.put(upload_data['presignedUrl'], data=file)
32
file2_url = upload_data['url']
33
print("File 2 uploaded successfully.")
34
35
# Merge the uploaded PDFs
36
merge_url = 'https://api.pdf.co/v1/pdf/merge'
37
payload = {
38
'url': [file1_url, file2_url],
39
'async': False
40
}
41
42
response = requests.post(merge_url, json=payload, headers=headers)
43
if response.status_code != 200:
44
raise Exception(f"PDF merge failed: {response.text}")
45
46
result = response.json()
47
if result['error']:
48
raise Exception(result['message'])
49
50
merged_url = result['url']
51
print(f"PDFs merged successfully. Merged file URL: {merged_url}")
52
53
# Download the merged file
54
response = requests.get(merged_url)
55
if response.status_code == 200:
56
with open('merged_output.pdf', 'wb') as file:
57
file.write(response.content)
58
print("Merged PDF downloaded successfully as 'merged_output.pdf'")
59
else:
60
print(f"Failed to download merged PDF: {response.text}")
61
62
except Exception as e:
63
print(f"An error occurred: {str(e)}")
Detecting PDF Form Fields

Use PDF.co’s API to identify form fields in a PDF. First, upload the PDF form, then identify the form fields, and finally, process and print the form fields.

1
import requests
2
3
# Replace with your actual PDF.co API key
4
API_KEY = 'YOUR_PDF_CO_API_KEY'
5
6
try:
7
# Upload the PDF form
8
upload_url = 'https://api.pdf.co/v1/file/upload/get-presigned-url'
9
headers = {'x-api-key': API_KEY}
10
payload = {'name': 'form.pdf'}
11
12
response = requests.post(upload_url, json=payload, headers=headers)
13
if response.status_code != 200:
14
raise Exception(f"File upload failed: {response.text}")
15
16
upload_data = response.json()
17
with open('path/to/your/form.pdf', 'rb') as file:
18
requests.put(upload_data['presignedUrl'], data=file)
19
file_url = upload_data['url']
20
print("PDF form uploaded successfully.")
21
22
# Identify form fields
23
fields_url = 'https://api.pdf.co/v1/pdf/info/fields'
24
payload = {
25
'url': file_url,
26
'async': False
27
}
28
29
response = requests.post(fields_url, json=payload, headers=headers)
30
if response.status_code != 200:
31
raise Exception(f"Form field identification failed: {response.text}")
32
33
result = response.json()
34
if result['error']:
35
raise Exception(result['message'])
36
37
# Process and print the form fields
38
fields = result['fields']
39
print(f"Found {len(fields)} form fields:")
40
for field in fields:
41
print(f"Name: {field['name']}")
42
print(f"Type: {field['type']}")
43
print(f"Value: {field['value']}")
44
print(f"Page: {field['page']}")
45
print(f"Rectangle: {field['rect']}")
46
print("---")
47
48
except Exception as e:
49
print(f"An error occurred: {str(e)}")
Filling PDF Form Fields

Use PDF.co’s API to fill form fields in a PDF. First, upload the PDF form, then fill the form fields, and finally, download the filled form.

1
import requests
2
import json
3
4
# Replace with your actual PDF.co API key
5
API_KEY = 'YOUR_PDF_CO_API_KEY'
6
7
# Replace with the path to your local PDF form
8
LOCAL_PDF_PATH = 'path/to/your/form.pdf'
9
10
# Replace with the desired output path for the filled form
11
OUTPUT_PDF_PATH = 'path/to/your/filled_form.pdf'
12
13
# Define the form fields to fill (replace with your actual field names and values)
14
FORM_FIELDS = {
15
'name': 'John Doe',
16
'email': 'john.doe@example.com',
17
'age': '30'
18
}
19
20
try:
21
# Step 1: Upload the PDF form
22
upload_url = 'https://api.pdf.co/v1/file/upload/get-presigned-url'
23
headers = {'x-api-key': API_KEY}
24
payload = {'name': 'form.pdf'}
25
26
response = requests.post(upload_url, json=payload, headers=headers)
27
if response.status_code != 200:
28
raise Exception(f"File upload failed: {response.text}")
29
30
upload_data = response.json()
31
with open(LOCAL_PDF_PATH, 'rb') as file:
32
requests.put(upload_data['presignedUrl'], data=file)
33
file_url = upload_data['url']
34
print("PDF form uploaded successfully.")
35
36
# Step 2: Fill the form fields
37
fill_url = 'https://api.pdf.co/v1/pdf/edit/fill-form'
38
payload = {
39
'url': file_url,
40
'fields': json.dumps(FORM_FIELDS),
41
'async': False
42
}
43
44
response = requests.post(fill_url, json=payload, headers=headers)
45
if response.status_code != 200:
46
raise Exception(f"Form filling failed: {response.text}")
47
48
result = response.json()
49
if result['error']:
50
raise Exception(result['message'])
51
52
filled_form_url = result['url']
53
print("Form filled successfully.")
54
55
# Step 3: Download the filled form
56
response = requests.get(filled_form_url)
57
if response.status_code != 200:
58
raise Exception("Failed to download the filled form")
59
60
with open(OUTPUT_PDF_PATH, 'wb') as file:
61
file.write(response.content)
62
print(f"Filled form downloaded and saved to {OUTPUT_PDF_PATH}")
63
64
except Exception as e:
65
print(f"An error occurred: {str(e)}")
DOCX to PDF Conversion

Use PDF.co’s API to convert a DOCX file to PDF. First, upload the DOCX file, then convert it to PDF, and finally, download the converted PDF.

1
# Replace with your actual PDF.co API key
2
API_KEY = 'YOUR_PDF_CO_API_KEY'
3
4
# Replace with the path to your local DOCX file
5
LOCAL_DOCX_PATH = 'path/to/your/document.docx'
6
7
# Replace with the desired output path for the PDF
8
OUTPUT_PDF_PATH = 'path/to/your/output.pdf'
9
10
try:
11
# Step 1: Upload the DOCX file
12
upload_url = 'https://api.pdf.co/v1/file/upload/get-presigned-url'
13
headers = {'x-api-key': API_KEY}
14
payload = {'name': 'document.docx'}
15
16
response = requests.post(upload_url, json=payload, headers=headers)
17
if response.status_code != 200:
18
raise Exception(f"File upload failed: {response.text}")
19
20
upload_data = response.json()
21
with open(LOCAL_DOCX_PATH, 'rb') as file:
22
requests.put(upload_data['presignedUrl'], data=file)
23
file_url = upload_data['url']
24
print("DOCX file uploaded successfully.")
25
26
# Step 2: Convert DOCX to PDF
27
convert_url = 'https://api.pdf.co/v1/pdf/convert/from/doc'
28
payload = {
29
'url': file_url,
30
'name': 'result.pdf',
31
'async': True
32
}
33
34
response = requests.post(convert_url, json=payload, headers=headers)
35
if response.status_code != 200:
36
raise Exception(f"Conversion initiation failed: {response.text}")
37
38
result = response.json()
39
if result['error']:
40
raise Exception(result['message'])
41
42
job_id = result['jobId']
43
print(f"Conversion job initiated. Job ID: {job_id}")
44
45
# Step 3: Wait for the conversion to complete
46
# NOTE: this is because we use 'async': True in the conversion request
47
# This is best suited for long running document conversions.
48
status_url = f'https://api.pdf.co/v1/job/check'
49
while True:
50
response = requests.post(status_url, json={'jobId': job_id}, headers=headers)
51
if response.status_code != 200:
52
raise Exception(f"Job status check failed: {response.text}")
53
54
status = response.json()
55
if status['status'] == 'working':
56
print("Conversion in progress...")
57
time.sleep(3)
58
elif status['status'] == 'success':
59
print("Conversion completed successfully.")
60
result_url = status['url']
61
break
62
else:
63
raise Exception(f"Conversion failed: {status['status']}")
64
65
# Step 4: Download the converted PDF
66
response = requests.get(result_url)
67
if response.status_code != 200:
68
raise Exception("Failed to download the converted PDF")
69
70
with open(OUTPUT_PDF_PATH, 'wb') as file:
71
file.write(response.content)
72
print(f"Converted PDF downloaded and saved to {OUTPUT_PDF_PATH}")
73
74
except Exception as e:
75
print(f"An error occurred: {str(e)}")

File Hosting

For file hosting, we recommend using your native cloud provider, such as AWS S3, Google Cloud Storage, or Azure Blob Storage.

Fileforge’s file hosting service will be discontinued on December 25th 2024. Files will have a capped date of December 25th 2024 until then.

Other Alternatives

A Final Thank You

As we wind down Fileforge, we want to extend our heartfelt thanks to every one of you who supported us along the way. Your feedback, usage, and trust helped us build something we’re proud of. While Fileforge’s chapter is coming to a close, our journey doesn’t end here, and we hope our paths will cross again in the future.

If you have any concerns or need further assistance during the migration process, please don’t hesitate to reach out. We’re here to make this transition as smooth as possible.

Thank you for being part of the Fileforge story.

Also on our blog