Integration prompt
Paste this into your coding assistant (Claude Code, Cursor, Codex, Copilot) to add SignSealer to your application. Fill in the block at the top; the assistant does the rest in the order a first integration goes, starting on a test key.
- Copy the prompt below (or its plain text), and paste it into your assistant.
- Fill in
<my_stack>: your framework, what is being signed, and how signers reach the page. - Review what it builds, and the test results it shows you, before you switch to a live key.
Or tell an agent: Read https://signsealer.com/docs/skill.md and follow it to add SignSealer to this project. It is the same prompt.
The prompt as plain text, to copy whole or to point an agent at.
# Add SignSealer e-signatures to my application
Integrate SignSealer (https://signsealer.com) so my application can send documents for
signature, or show the signing page inside it, and act when they are signed.
Read the docs as you go: every page is Markdown at https://signsealer.com/docs/<page>.md, and
https://signsealer.com/llms-full.txt is all of them in one file.
## My application
<my_stack>
Stack: [framework and language, e.g. Next.js 15 + TypeScript, Django, Rails, Laravel, Express]
What signs: [waivers | rental agreements | contracts | onboarding forms | other]
How signers get the page: [we email/text them (SignSealer sends) | inside our app (embedded) | both]
Who the signer is in my app: [the table and id that identify a person, e.g. bookings.id or users.id]
Database: [Postgres | MySQL | SQLite | Mongo | other]
Templates: [already made in the SignSealer dashboard | create them from code]
</my_stack>
## Rules
- Never invent an SDK method, a route, a field, an event name or a result. If
the docs do not show it, it does not exist: say so and stop.
- The API key is server-side only. Read it from SIGNSEALER_KEY. Never send it
to a browser, a mobile app or a log line.
- Start with a test key (mk_test_...). Nothing is emailed, texted or billed
from the sandbox, and webhooks are delivered the same way. Move to a live
key (mk_live_...) only when everything below passes.
- Never store a signing link. It is a bearer credential. Mint a fresh one when
the page is shown (embedded), or send a reminder, which carries a fresh one.
- Never trust a signer id or document id that came from the browser. Look it
up from the person who is signed in to my app.
- Verify every webhook against the raw request body before parsing it, and
deduplicate on the SignSealer-Event-Id header: delivery is at least once.
- Send an Idempotency-Key on every POST that creates something (the SDKs do it
for you), so a retry never makes a second document.
## Step 1: the client
Node: npm install @signsealer/sdk (no dependencies). Python: pip install
signsealer. PHP: composer require signsealer/sdk. Any other language: the REST
API at https://api.signsealer.com with "Authorization: Bearer $SIGNSEALER_KEY",
described by https://signsealer.com/openapi.json. Confirm the key with GET /v1/account, which
answers "mode": "test" for a test key.
## Step 2: the template
If the business made its templates in the dashboard, list them with
GET /v1/templates and use the code. Otherwise create one with POST /v1/templates
(every {{placeholder}} declared in "variables") and publish it with
POST /v1/templates/{id}/publish. A published version never changes; revise
with POST /v1/templates/{id}/revise. See https://signsealer.com/docs/templates.md.
## Step 3: a document, and who signs it
POST /v1/documents with "template_code" and "values" for every placeholder.
Then POST /v1/documents/{id}/send with "signers": each has a full_name and an
email, a phone, or both. Store the document id and each signer id against the
person in my database. See https://signsealer.com/docs/quickstart.md.
## Step 4 (embedded only): the signing page inside my app
Send with "delivery": "embedded" on the signer, so nothing is emailed. When
the person opens my screen, call POST /v1/documents/{id}/signers/{signer}/embed
for a fresh url and put it in an iframe (allow="camera; geolocation"). The
page may be framed only on a site the business has proven: "frame_origins" in
the answer lists them, and empty means nowhere yet. Listen for the page's
postMessage events (source "signsealer"). See https://signsealer.com/docs/embedding.md.
## Step 5: the webhook
On start-up, PUT /v1/webhooks with my endpoint's url and the events I need
(signing.completed at least; signing.declined, signing.expired and
signing.viewed are often wanted). It never makes a second endpoint; keep the
"secret" it returns when "created" is true. In the handler, verify with the
SDK's verifyWebhookRequest (Node) or its Python and PHP equivalents, or by
hand: SignSealer-Signature is v1=<hex>, HMAC-SHA256 of "timestamp.body" with
the secret, and SignSealer-Timestamp must be within five minutes. Answer 2xx
within ten seconds and do the work after. On signing.completed, fetch
GET /v1/documents/{id} and the signed PDF from GET /v1/documents/{id}/pdf.
See https://signsealer.com/docs/webhooks.md.
## Step 6: errors
Every error is { "error": { "code", "message", "hint" } }. Show the message;
retry only 429 (after Retry-After) and 5xx, with the same Idempotency-Key.
402 quota_exceeded means the business is out of signings: tell a person, do
not retry. See https://signsealer.com/docs/errors.md.
## Before it goes live
1. With the test key: create, send, and sign it -- from the link yourself, or
with POST /v1/documents/{id}/signers/{signer}/simulate and "outcome":
"signed" -- and see signing.completed arrive, verified, exactly once.
2. Send the same webhook twice by hand and check the second does nothing.
3. Change one byte of a delivery and check it is refused.
4. Decline a document ("outcome": "declined") and let one expire
("outcome": "expired"), and check my app shows both.
5. Embedded: open the page twice and check the first link stops working.
6. Show me the code and the test results before switching to the live key.
Why these rules
- Never invent. An assistant that cannot find a method writes one that looks right. The prompt tells it to stop instead; every route, field and event it names is on these pages.
- A link is a credential. Whoever holds a signing link can sign. Kept in a database, a link is a signature waiting to be taken; minted when shown, it is one person's for one visit.
- The raw body. The signature covers the bytes sent. Parsing and re-serialising checks your formatter, not ours, and one day they disagree.
- A test key first. The sandbox sends nothing and bills nothing, and delivers webhooks the same way, so the whole road can be driven before a customer sees it.
Building with an assistant that connects to SignSealer itself instead, to send and check documents for a business? That is AI assistants (MCP).
This page as Markdown Ask an AI about it: ChatGPT · Claude · Perplexity · Google AI · Grok
Ready to build? An API key takes a minute in the portal, and the free plan covers the first 10 agreements a month.
Get an API key