Turn any PDF into a legally-binding, sealed, certificate-backed signed document — from your own backend.
# 1. Create an envelope from a PDF (returns {"ok":true,"id":42}) curl https://sign.liftedholdings.com/api/mysign/agreements \ -H "Authorization: Bearer $LIFTED_SIGN_KEY" \ -F file=@contract.pdf \ -F name="Master Services Agreement" # 2. Add a signer (JSON, replaces the signer set) curl https://sign.liftedholdings.com/api/mysign/agreements/42/signers \ -H "Authorization: Bearer $LIFTED_SIGN_KEY" \ -H "Content-Type: application/json" \ -d '{"signers":[{"name":"Dana Client","email":"dana@example.com"}]}' # 3. Drop a signature wherever the doc says "Signature:" — no coordinates curl https://sign.liftedholdings.com/api/mysign/agreements/42/fields \ -H "Authorization: Bearer $LIFTED_SIGN_KEY" \ -H "Content-Type: application/json" \ -d '{"fields":[{"signer":"dana@example.com","type":"signature","anchor":"Signature:"}]}' # 4. Send it — freezes the PDF, emails each signer a single-use link curl https://sign.liftedholdings.com/api/mysign/agreements/42/send \ -H "Authorization: Bearer $LIFTED_SIGN_KEY" \ -X POST
Authenticate every request with a Bearer key (sk_live_… / sk_test_…). Mint one in the Developers tab — it’s shown once. Step 3 places fields by anchor — name text that already exists in the document and the field snaps to it, no coordinate math. Need pixel control? A field can also take absolute PDF points or normalized 0..1 coordinates — see the Fields reference. Send the same document often? Build it once as a template, mark the fields you fill as prefill, then spin up a ready-to-send draft any time with POST /templates/{id}/use and an answers map.
# pip install nothing — standard library only. Python 3.8+ from lifted_sign import LiftedSign ls = LiftedSign(api_key="$LIFTED_SIGN_KEY") env = ls.create_agreement("contract.pdf", name="Master Services Agreement") ls.add_signers(env["id"], [{"name": "Dana Client", "email": "dana@example.com"}]) ls.place_fields(env["id"], [ {"signer": "dana@example.com", "type": "signature", "anchor": "Signature:"}, {"signer": "dana@example.com", "type": "date", "anchor": "Date:"}, ]) ls.send(env["id"]) # each signer gets a single-use link
// no npm install — built-in fetch/FormData. Node 18+ import { LiftedSign } from "./lifted-sign.mjs"; const ls = new LiftedSign({ apiKey: "$LIFTED_SIGN_KEY" }); const env = await ls.createAgreement("contract.pdf", { name: "Master Services Agreement" }); await ls.addSigners(env.id, [{ name: "Dana Client", email: "dana@example.com" }]); await ls.placeFields(env.id, [ { signer: "dana@example.com", type: "signature", anchor: "Signature:" }, { signer: "dana@example.com", type: "date", anchor: "Date:" }, ]); await ls.send(env.id); // each signer gets a single-use link
# requires curl + jq — the whole flow, no SDK export LIFTED_SIGN_KEY=sk_live_xxx AID=$(curl -fsS -H "Authorization: Bearer $LIFTED_SIGN_KEY" \ -F file=@contract.pdf -F name="MSA" \ https://sign.liftedholdings.com/api/mysign/agreements | jq -r .id) curl -fsS -H "Authorization: Bearer $LIFTED_SIGN_KEY" -H "Content-Type: application/json" \ -d '{"signers":[{"name":"Dana Client","email":"dana@example.com"}]}' \ https://sign.liftedholdings.com/api/mysign/agreements/$AID/signers curl -fsS -H "Authorization: Bearer $LIFTED_SIGN_KEY" -H "Content-Type: application/json" \ -d '{"fields":[{"signer":"dana@example.com","type":"signature","anchor":"Signature:"}]}' \ https://sign.liftedholdings.com/api/mysign/agreements/$AID/fields curl -fsS -H "Authorization: Bearer $LIFTED_SIGN_KEY" -X POST \ https://sign.liftedholdings.com/api/mysign/agreements/$AID/send
Same four steps in every language: create an envelope, add a signer, place a signature by anchor, send. Get the runnable file on the right — it doubles as a CLI: python lifted_sign.py contract.pdf dana@example.com.