Skip to content

Latest commit

 

History

History
162 lines (118 loc) · 5.61 KB

README.md

File metadata and controls

162 lines (118 loc) · 5.61 KB

kovapdf

The official KovaPDF client for Python, with the kovapdf command line tool. Compress, merge, split, reorder, convert, read scans, redact and check the signatures of PDF files, convert Bangla and Hindi text between Bijoy, Kruti Dev and Unicode, and send documents for signature.

The work is done by KovaPDF: https://www.kovapdf.com

Install

pip install kovapdf

Python 3.10 or newer. No dependencies: only the standard library.

Your API key

Make a key in your KovaPDF dashboard (Developer API) and put it in the environment. The client reads KOVAPDF_API_KEY; never write a key into code.

export KOVAPDF_API_KEY=kova_test_...

A test key (kova_test_) is free to make and stamps its PDFs TEST. A live key (kova_live_) needs API access on your account.

Use it

from kovapdf import KovaPDF

kova = KovaPDF()  # the key comes from KOVAPDF_API_KEY

result = kova.compress("report.pdf", level="strong", save_to="report-small.pdf")
print(result.saved)        # ['report-small.pdf']
print(result.attribution)  # Done with KovaPDF (kovapdf.com).

Every tool has its own method, made from KovaPDF's tool manifest: compress, merge, split, organize, convert, ocr, redact, bijoy_to_unicode, unicode_to_bijoy, kruti_to_unicode and verify_job.

kova.merge(["a.pdf", "b.pdf"], save_to="merged.pdf")
kova.split("big.pdf", mode="range", pages="1-3,5", save_to="out/")
print(kova.bijoy_to_unicode(text="Avwg evsjvq Mvb MvB").text)

A file can be a path, an https address, bytes, an open file, or a dict: {"file_id": ...} from an earlier upload, {"url": ...}, or {"data": b"...", "name": "a.pdf"}.

Step by step

f = kova.files.upload("in.pdf")                       # kept for one hour
job = kova.jobs.create("compress", [f["id"]], {"level": "basic"})
done = kova.jobs.wait(job["id"], timeout=300)
data = kova.download(done["result"]["files"][0]["download"]["url"])  # the link works for 15 minutes

kova.run(tool, inputs, options) does all of that in one call.

Signature requests and verify

request = kova.sign_requests.create("agreement.pdf", {
    "title": "Service agreement",
    "sequential": False,
    "signers": [{"name": "Alex Rivera", "email": "alex@example.com", "order": 1}],
    "fields": [{"signer": 0, "kind": "SIGNATURE", "page": 1, "x": 72, "y": 640, "width": 180, "height": 48}],
})
kova.sign_requests.list()
kova.sign_requests.get(request["id"])
kova.sign_requests.remind(request["id"])
kova.sign_requests.cancel(request["id"])
pdf = kova.sign_requests.document(request["id"], version="final")

report = kova.verify("signed.pdf")  # every digital signature, checked

Webhooks

from kovapdf import verify_webhook

# raw_body: the request body exactly as received, before JSON parsing
event = verify_webhook(raw_body, request.headers, os.environ["KOVAPDF_WEBHOOK_SECRET"])

It checks the KovaPDF-Signature header (t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<body>">) and refuses a timestamp older than five minutes.

Command line

kovapdf compress in.pdf -o out.pdf --level strong
kovapdf merge a.pdf b.pdf -o merged.pdf
kovapdf verify signed.pdf
kovapdf bijoy-to-unicode "Avwg evsjvq Mvb MvB"
echo "Avwg" | kovapdf bijoy-to-unicode
kovapdf tools                    # every tool and its options
python -m kovapdf --help

The command prints Done with KovaPDF (kovapdf.com). after each result. It never overwrites a file unless you add --force.

Errors

Every error is a KovaPDFError with a stable code and a message you can show to a person. A few need care:

code what it means
integration_paused KovaPDF has paused connections from this kind of app for now. Nothing was changed. Try again later, or use https://www.kovapdf.com.
tool_paused This tool is paused for apps right now. It still works on https://www.kovapdf.com.
not_available This KovaPDF feature is not available yet.
limit_reached, rate_limited, daily_limit A limit was reached; retry_after says when to try again.
timeout The job is still running; ask for it later with jobs.get(id).

Paused answers are never retried.

Limits, and how the client behaves

Your account's own limits apply, exactly as on the website; your dashboard shows them. Files you upload and results are deleted within an hour, and a result link works for 15 minutes.

The client is gentle with KovaPDF by design:

  • at most 2 calls at once per client, across threads (you can set up to 4);
  • a job is checked no more often than every 2 seconds, slowing to every 10;
  • Retry-After is always honoured; otherwise it waits 2 seconds, then longer (up to a minute), and tries at most 5 more times, only after a busy answer or a network error;
  • every call says who it is: User-Agent: kovapdf-sdk-python/<version> (+https://www.kovapdf.com) and X-KovaPDF-Client: sdk.

Attribution

Results carry attribution = "Done with KovaPDF (kovapdf.com).". Please show it to the person you did the work for, with a link to https://www.kovapdf.com.

Development

src/kovapdf/_generated.py is made from KovaPDF's tool manifest and OpenAPI file by packages/sdk-js/scripts/generate.mjs in the KovaPDF repository; a test fails when it drifts. Run the tests with:

python -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/pytest

Licence

MIT for the code (see LICENSE). The KovaPDF name, logos and images are not covered by it (see NOTICE).