Appearance
The signature appearance is controlled entirely by JSON option keys passed toatick.signPfx(pdf, pfx, optionsJson). By default ATick shows its logo on the left, the signer details on the right, and the validity mark.
const atick = require("atick");
const fs = require("fs");
const pdf = fs.readFileSync("doc.pdf");
const pfx = fs.readFileSync("my.pfx");
const signed = atick.signPfx(pdf, pfx, JSON.stringify({
cn: "Axonate Tech", // common name (shown bold after "Digitally Signed by:")
org: "Acme Corp", // organisation line
reason: "Approved", // "Reason: …"
location: "New Delhi", // "Location: …"
green_tick: true,
}));
fs.writeFileSync("signed.pdf", signed);Long signer names wrap onto more lines instead of shrinking the font, so the box never overflows.
Date / time
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket" })); // current time (default)
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", date: "Signed on 10-Jun-2026" })); // a fixed string
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", date: "" })); // no date lineThe left side
The image key controls what is drawn on the left of the appearance:
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket" })); // default: the ATick logo
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", image: "none" })); // no logo
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", image: "cn" })); // the CN as large text on the LEFT (Adobe-style)image value | Result |
|---|---|
| omitted | the default ATick logo |
"none" | no logo on the left |
"cn" | the signer name as text on the left instead of a logo |
The validity mark — ATick's signature look
The mark sits centred in the appearance and tells the reader the signature's status at a glance:
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", green_tick: true })); // the "?" mark — Adobe paints it GREEN if valid+trusted, RED if invalid
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", always_check: true })); // ATick's green-tick graphic as the base (Adobe still reds a bad signature)
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", green_tick: false })); // no mark — a plain signaturegreen_tick: true— the classic validity mark: a?that Adobe Acrobat repaints green for a valid, trusted signature and red for a broken one.always_check: true— uses ATick's own green-tick graphic as the base, so the tick shows in every viewer; Adobe still overlays a red mark if the signature is actually invalid.green_tick: false— no mark; a plain signature appearance.
How Adobe shows it
When the certificate is valid and trusted, Adobe Reader / Acrobat reports “Signed and all signatures are valid” and paints the tick green — exactly the reassurance your readers expect.
Every state Adobe can show
ATick draws the appearance and the mark; Adobe then colours the mark based on the signature's validity and whether it trusts the certificate, so your reader instantly sees the status:
- Valid & trusted — signature intact and the certificate chains to a root Adobe trusts — “Signed and all signatures are valid.”
- Validity unknown — signature intact, but Adobe doesn't trust the certificate's root — “Validity unknown.”
- Not verified — Adobe hasn't validated the signature yet (no trust information) — “Signature not verified.”
- Invalid — the document was changed after signing (or the signature is broken) — “Signature is invalid.”
So the green tick appears only when the signature is valid and the signer's certificate chains to a root Adobe trusts (the Adobe Approved Trust List, or your organisation's trust). The same ATick appearance shows the question-mark or red-cross state automatically — you don't draw those; Adobe does.
Colouring the mark
Colour the mark with a hex string, a CSS colour name, or an [r, g, b] array — or fill it with an axial gradient:
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", green_tick: true, mark_color: "#E53935" })); // hex
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", green_tick: true, mark_color: "blue" })); // CSS name
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", green_tick: true, mark_color: [255, 140, 0] })); // RGB array
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", green_tick: true, mark_gradient: ["red", "orange", "yellow"] })); // gradientUse mark_scale to resize the mark relative to the appearance box.
Distinguished name
atick.signPfx(pdf, pfx, JSON.stringify({
cn: "Axonate Tech",
dn: "CN=Axonate Tech, O=Personal, C=IN",
}));The DN is shown directly under the "Digitally Signed by:" line.
Custom-text-only appearance
Show only your own text — no "Signed by", no date, no CN structure. Inside body, \n starts a new line and *word* makes that runbold:
atick.signPfx(pdf, pfx, JSON.stringify({
body: "*APPROVED*\nReviewed by: *Axonate Tech*\nThis document is *legally binding*.",
}));In a JavaScript string literal,\nis a real newline character.JSON.stringifythen encodes it correctly inside the JSON, and ATick reads it as a line break.
Positioning the appearance
Place the appearance with page + rect, or stamp several positions at once with placements. Coordinates are PDF points as [x1, y1, x2, y2].
atick.signPfx(pdf, pfx, JSON.stringify({
cn: "Aniket", green_tick: true, page: 1, rect: [300, 55, 575, 175],
}));
// one stamp per entry: [page, [x1,y1,x2,y2]]
atick.signPfx(pdf, pfx, JSON.stringify({
cn: "Aniket", green_tick: true,
placements: [[1, [300, 55, 575, 175]], [2, [300, 55, 575, 175]]],
}));You can also size the box directly with width and height.
Fine-tuning the layout
When the default placement is close but not exact, nudge the pieces individually instead of redesigning the box. All offsets are in PDF points unless noted.
atick.signPfx(pdf, pfx, JSON.stringify({
cn: "Aniket", green_tick: true,
top_reserve: 0.32, // reserve the top 32% of the box for the logo / mark
mark_scale: 1.2, // make the mark 20% larger
mark_dx: 4, // nudge the mark right
mark_dy: -2, // nudge the mark down
text_dx: 6, // nudge the signer text right
text_top: 4, // push the text down from the top
}));top_reserve— fraction (0–1) of the box height kept clear at the top for the logo or validity mark; raise it to give the mark more room above the text.mark_scale— scale factor for the mark relative to the box;mark_dx/mark_dyshift it horizontally / vertically.text_dx— horizontal shift of the signer text;text_top— vertical offset of the text from the top of the box.
Border colour & width
With border: true, set the border colour and line width:
atick.signPfx(pdf, pfx, JSON.stringify({
cn: "Aniket", green_tick: true,
border: true,
border_color: [33, 150, 243], // [r, g, b] (also accepts hex or a CSS name)
border_width: 1.0, // line width in PDF points
}));border_color— a hex string, a CSS colour name, or an[r, g, b]array.border_width— border line width in PDF points (e.g.1.0).
Invisible signature
A cryptographically valid signature that draws nothing on the page — pass an emptyplacements array:
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", placements: [] })); // empty placementsOther appearance options
| Key | Purpose |
|---|---|
heading | the heading line at the top of the appearance |
text | extra free text line |
ou | organisational-unit line |
font_size | size of the appearance text |
text_color | colour of the text |
bg_color | background fill of the box |
border | draw a border around the box |
border_color | border colour (hex / name / [r,g,b]) — used with border: true |
border_width | border line width in PDF points |
width, height | the box size |
top_reserve | top fraction (0–1) reserved for the logo / mark |
mark_scale | scale factor for the validity mark |
mark_dx, mark_dy | nudge the mark horizontally / vertically (PDF points) |
text_dx, text_top | nudge the signer text horizontally / from the top (PDF points) |
Errors
Every failure throws an Error:
try {
atick.signPfx(pdf, pfx, JSON.stringify({ cn: "Aniket", image: "missing.png" }));
} catch (err) {
console.log("signing failed: " + err.message);
}