Skip to content

Commit 6b042e8

Browse files
committed
initial commit for python library for api2pdf.com
1 parent ada2846 commit 6b042e8

File tree

5 files changed

+332
-0
lines changed

5 files changed

+332
-0
lines changed

LICENSE.txt

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Api2Pdf
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
# Api2Pdf - Python
2+
[Api2Pdf.com](https://www.api2pdf.com) | [Docs](https://www.api2pdf.com/documentation)
3+
4+
## What is Api2Pdf?
5+
Api2Pdf.com is a service for instantly generating PDFs from:
6+
- HTML
7+
- URLs
8+
- Microsoft Office documents (Word, Excel, Powerpoint)
9+
- Images
10+
- Merge / Concatenate two or more PDFs
11+
12+
Api2Pdf provides access to **wkhtmltopdf**, **Headless Chrome**, and **LibreOffice**, along with the ability merge / concatenate PDFs together.
13+
14+
15+
16+
## Get Started
17+
This python library provides convenient methods for accessing the REST API [documented here](https://www.api2pdf.com/documentation/).
18+
19+
### Acquire API Key
20+
1. Create an account and login at [portal.api2pdf.com](https://portal.api2pdf.com)
21+
2. Add a balance to your account (no monthly commitment, sign up with as little as $1)
22+
3. Create an application and grab your API Key
23+
24+
### Install
25+
pip install api2pdf
26+
27+
### Usage
28+
29+
from api2pdf import Api2Pdf
30+
31+
a2p = Api2PDF('YOUR-API-KEY')
32+
api_response = a2p.HeadlessChrome.convert_from_html('<p>Hello, World</p>')
33+
print(api_response.result)
34+
35+
### Sample Result
36+
37+
An `Api2PdfResponse` object is returned from every API call. Call the `result` attribute to retrieve the data. If a call is unsuccessful then `success` will show False and the `error` will provide the reason for failure. Additional attributes include the total data usage in, out, and the cost for the API call.
38+
39+
{
40+
'pdf': 'https://link-to-pdf-only-available-for-24-hours',
41+
'mbIn': 0.08421039581298828,
42+
'mbOut': 0.08830547332763672,
43+
'cost': 0.00017251586914062501,
44+
'success': True,
45+
'error': None,
46+
'responseId': '6e46637a-650d-46d5-af0b-3d7831baccbb'
47+
}
48+
49+
For debugging, you can simply print the `Api2PdfResponse` object to see the request and response data.
50+
51+
links_to_pdfs = ['https://LINK-TO-PDF', 'https://LINK-TO-PDF']
52+
merge_result = a2p.merge(links_to_pdfs)
53+
print(api_response)
54+
55+
Output:
56+
57+
---- API2PDF REQUEST ----
58+
- Headers: {'Authorization': 'f8bd6792-f1cd-42df-9bf9-f7a35e59362f'}
59+
- Endpoint: https://v2018.api2pdf.com/merge
60+
- Payload:
61+
['https://LINK-TO-PDF', 'https://LINK-TO-PDF']
62+
---- API2PDF RESPONSE ----
63+
{'pdf': 'https://link-to-pdf-only-available-for-24-hours', 'mbIn': 0.08421039581298828, 'mbOut': 0.08830547332763672, 'cost': 0.00017251586914062501, 'success': True, 'error': None, 'responseId': '163c4d25-25d7-4b82-bf50-907597d2ad46'}
64+
65+
66+
## Documentation
67+
68+
### Convert HTML to PDF
69+
70+
We support both **wkhtmltopdf** and **Headless Chrome** with the endpoint to convert raw html to PDFs. Both endpoints allow you to pass keyword arguments that are options available for their respective libraries.
71+
72+
##### HeadlessChrome.convert_from_html(html, **options)
73+
##### WkHtmlToPdf.convert_from_html(html, **options)
74+
75+
from api2pdf import Api2Pdf
76+
a2p = Api2PDF('YOUR-API-KEY')
77+
78+
# headless chrome
79+
headless_chrome_result = a2p.HeadlessChrome.convert_from_html('<p>Hello World</p>')
80+
print(headless_chrome_result.result)
81+
82+
# wkhtmltopdf
83+
wkhtmltopdf_result = a2p.WkHtmlToPdf.convert_from_html('<p>Hello World</p>')
84+
print(wkhtmltopdf_result.result)
85+
86+
### Convert URL to PDF
87+
88+
We support both wkhtmltopdf and Headless Chrome with the endpoint to convert urls to PDFs. Both endpoints allow you to pass keyword arguments that are options available for their respective libraries.
89+
90+
##### HeadlessChrome.convert_from_url(url, **options)
91+
92+
##### WkHtmlToPdf.convert_from_url(url, **options)
93+
94+
from api2pdf import Api2Pdf
95+
a2p = Api2PDF('YOUR-API-KEY')
96+
97+
# headless chrome
98+
headless_chrome_result = a2p.HeadlessChrome.convert_from_url('https://LINK-TO-YOUR-WEBSITE')
99+
print(headless_chrome_result.result)
100+
101+
# wkhtmltopdf
102+
wkhtmltopdf_result = a2p.WkHtmlToPdf.convert_from_url('https://LINK-TO-YOUR-WEBSITE')
103+
print(wkhtmltopdf_result.result)
104+
105+
### Convert Microsoft Office Documents and Images to PDF
106+
107+
We use **LibreOffice** to convert the following formats to PDF:
108+
109+
- doc, docx, xls, xlsx, ppt, pptx, gif, jpg, png, bmp, rtf, txt, html
110+
111+
You must provide a url to the file. Our engine will consume the file at that URL and convert it to the PDF.
112+
113+
##### LibreOffice.convert_from_url(url)
114+
115+
from api2pdf import Api2Pdf
116+
a2p = Api2PDF('YOUR-API-KEY')
117+
118+
libreoffice_result = a2p.LibreOffice.convert_from_html('https://LINK-TO-YOUR-FILE')
119+
print(libreoffice_result.result)
120+
121+
### Merge / Concatenate Two or More PDFs
122+
123+
To use the merge endpoint, supply a list of urls to existing PDFs. The engine will consume all of the PDFs and merge them into a single PDF, in the order in which they were provided in the list.
124+
125+
##### merge(list_of_urls)
126+
127+
from api2pdf import Api2Pdf
128+
a2p = Api2PDF('YOUR-API-KEY')
129+
130+
# merge pdfs
131+
links_to_pdfs = ['https://LINK-TO-PDF', 'https://LINK-TO-PDF']
132+
merge_result = a2p.merge(links_to_pdfs)
133+
print(merge_result.result)
134+
135+
### Helper Methods
136+
137+
##### Api2PdfResponse: download_pdf()
138+
139+
On any `Api2PdfResponse` that succesfully generated a pdf, you can use the handy download_pdf() method to download the pdf to a file-like object which you can then save to your local cache. If the pdf generation was unsuccessful, it will throw a FileNotFoundException.
140+
141+
from api2pdf import Api2Pdf
142+
a2p = Api2PDF('YOUR-API-KEY')
143+
144+
# merge pdfs
145+
links_to_pdfs = ['https://LINK-TO-PDF', 'https://LINK-TO-PDF']
146+
merge_result = a2p.merge(links_to_pdfs)
147+
148+
pdf_as_file_object = merge_result.download_pdf()
149+
150+
151+
## FAQ
152+
153+
#### How do you bill?
154+
$1 will be deducted from your balance every month as long as you maintain an active account. This charge begins 30 days after your first sign up for the service. In addition, we charge $0.001 per megabyte (data in + data out). We require customers to maintain a positive balance on their account to use the service. You can turn off auto-recharge at any time and let your funds run out if you no longer wish to use the service. See our [pricing calculator](https://www.api2pdf.com/pricing/).
155+
156+
#### Do you offer free accounts?
157+
The average customer spents about $2/month on our product. We do not have free accounts as this time. Feel free to check out alternatives and competitors.
158+
159+
#### Cancellation and refunds
160+
We do not have any long term contracts. You can leave us at anytime with no further commitments. As our minimum cost is $1.00, we do not provide refunds.
161+
162+
#### Are there any limits?
163+
Api2Pdf does not set any specific limits on PDF file size, however our system does have processing power limitations. Each PDF request is provided 3 GB of RAM to work with and 110 seconds to generate the PDF. We offer WKHTMLTOPDF, Headless Chrome, and LibreOffice to do conversions. Our platform will have the same limits as those underlying components. If the underlying component fails to convert to PDF, it will also fail via our service. Some examples are:
164+
165+
- Password protected PDFs
166+
- Encrypted PDFs
167+
- HTML that references erroneous content
168+
- Protected Office Documents
169+
170+
#### How long are PDFs stored on Api2Pdf.com?
171+
After generating a PDF via the API, you are provided with a link to the file. This link will hold the PDF for 24 hours. If you wish to keep your PDF long term, download the file to your local cache.

api2pdf/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .api2pdf import *
2+
name = 'api2pdf'

api2pdf/api2pdf.py

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import requests
2+
import json
3+
4+
API2PDF_BASE_ENDPOINT = 'https://v2018.api2pdf.com'
5+
API2PDF_MERGE_ENDPOINT = API2PDF_BASE_ENDPOINT + '/merge'
6+
API2PDF_WKHTMLTOPDF_HTML = API2PDF_BASE_ENDPOINT + '/wkhtmltopdf/html'
7+
API2PDF_WKHTMLTOPDF_URL = API2PDF_BASE_ENDPOINT + '/wkhtmltopdf/url'
8+
API2PDF_CHROME_HTML = API2PDF_BASE_ENDPOINT + '/chrome/html'
9+
API2PDF_CHROME_URL = API2PDF_BASE_ENDPOINT + '/chrome/url'
10+
API2PDF_LIBREOFFICE_CONVERT = API2PDF_BASE_ENDPOINT + '/libreoffice/convert'
11+
12+
class Api2Pdf(object):
13+
def __init__(self, api_key):
14+
self.api_key = api_key
15+
16+
@property
17+
def WkHtmlToPdf(self):
18+
return Api2Pdf_WkHtmlToPdf(self.api_key)
19+
20+
@property
21+
def HeadlessChrome(self):
22+
return Api2Pdf_HeadlessChromeToPdf(self.api_key)
23+
24+
@property
25+
def LibreOffice(self):
26+
return Api2Pdf_LibreOffice(self.api_key)
27+
28+
def merge(self, list_of_urls):
29+
return self._make_request(API2PDF_MERGE_ENDPOINT, list_of_urls)
30+
31+
def _make_html_payload(self, html, **options):
32+
payload = {
33+
'html': html,
34+
}
35+
if options != None:
36+
payload['options'] = options
37+
return payload
38+
39+
def _make_url_payload(self, url, **options):
40+
payload = {
41+
'url': url
42+
}
43+
if options != None:
44+
payload['options'] = options
45+
return payload
46+
47+
def _make_request(self, endpoint, payload):
48+
headers = {'Authorization': self.api_key}
49+
payload_as_json = json.dumps(payload)
50+
response = requests.post(endpoint, data=payload_as_json, headers=headers)
51+
return Api2PdfResponse(headers, endpoint, payload, response)
52+
53+
class Api2Pdf_WkHtmlToPdf(Api2Pdf):
54+
def convert_from_html(self, html, **options):
55+
payload = self._make_html_payload(html, **options)
56+
return self._make_request(API2PDF_WKHTMLTOPDF_HTML, payload)
57+
58+
def convert_from_url(self, url, **options):
59+
payload = self._make_url_payload(url, **options)
60+
return self._make_request(API2PDF_WKHTMLTOPDF_URL, payload)
61+
62+
class Api2Pdf_HeadlessChromeToPdf(Api2Pdf):
63+
def convert_from_html(self, html, **options):
64+
payload = self._make_html_payload(html, **options)
65+
return self._make_request(API2PDF_CHROME_HTML, payload)
66+
67+
def convert_from_url(self, url, **options):
68+
payload = self._make_url_payload(url, **options)
69+
return self._make_request(API2PDF_CHROME_URL, payload)
70+
71+
class Api2Pdf_LibreOffice(Api2Pdf):
72+
def convert_from_url(self, url):
73+
payload = self._make_url_payload(url)
74+
return self._make_request(API2PDF_LIBREOFFICE_CONVERT, payload)
75+
76+
class Api2PdfResponse(object):
77+
def __init__(self, headers, endpoint, payload_as_json, response):
78+
self.headers = headers
79+
self.endpoint = endpoint
80+
self.payload_as_json = payload_as_json
81+
self._result = json.loads(response.text)
82+
83+
@property
84+
def request(self):
85+
request_info = {
86+
'headers': self.headers,
87+
'endpoint': self.endpoint,
88+
'payload': self.payload_as_json,
89+
}
90+
return request_info
91+
92+
@property
93+
def result(self):
94+
return self._result
95+
96+
def download_pdf(self):
97+
USERAGENT = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
98+
if self.result['success']:
99+
downloaded_pdf = requests.get(pdf_response['pdf'], headers=USERAGENT)
100+
data = download_response.content
101+
return data
102+
else:
103+
raise FileNotFoundError("PDF never generated " + self.result['error'])
104+
105+
def __str__(self):
106+
return """
107+
---- API2PDF REQUEST ----
108+
- Headers: {0}
109+
- Endpoint: {1}
110+
- Payload:
111+
{2}
112+
---- API2PDF RESPONSE ----
113+
{3}
114+
""".format(self.headers, self.endpoint, self.payload_as_json, self.result)

setup.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import setuptools
2+
3+
with open("README.md", "r") as fh:
4+
long_description = fh.read()
5+
6+
setuptools.setup(
7+
name="api2pdf",
8+
version="0.0.4",
9+
author="Zack Schwartz",
10+
author_email="support@api2pdf.com",
11+
description="Wrapper for api2pdf.com library for converting html, urls, and word documents to pdf",
12+
long_description=long_description,
13+
long_description_content_type="text/markdown",
14+
url="https://github.com/api2pdf/api2pdf.python",
15+
packages=setuptools.find_packages(),
16+
install_requires=[
17+
'requests',
18+
],
19+
classifiers=(
20+
"Programming Language :: Python :: 3",
21+
"License :: OSI Approved :: MIT License",
22+
"Operating System :: OS Independent",
23+
),
24+
)

0 commit comments

Comments
 (0)