E-signature API code examples · cURL, Node, Python, PHP, Ruby

E-signature API code examples. Send your first envelope in five minutes.

Get your API key. 25 documents free, no card. Copy the e-signature API code example for your stack, set your key, and run it. 25¢ per envelope, sent by text, email, or both, with no monthly fee.

✓25¢ per envelope ✓Text and email ✓No monthly fee
Continue with Google
or use your work email

25 documents free. No card needed.

Check your email

We sent a sign-in link to . It is good for 15 minutes, and your API key is waiting on the other side.

B64=$(base64 < agreement.pdf | tr -d '\n')
API=https://api.esigndev.com/v1/envelopes
AUTH="Authorization: Bearer $SIGLIO_API_KEY"

# 1. Send it, by text and email
ENV_ID=$(curl -s $API -H "$AUTH" -H "Content-Type: application/json" -d '{
  "document_name": "Service agreement", "document_base64": "'"$B64"'",
  "delivery": "both", "sender": { "company_name": "Your Company" },
  "signer": { "name": "Jane Smith", "email": "jane@example.com", "phone": "+18135551212" }
}' | sed -E 's/.*"id":"(env_[a-z0-9]+)".*/\1/')

# 2. Check where it stands
curl -s $API/$ENV_ID -H "$AUTH"

# 3. Once it is completed, download the signed PDF
curl -s $API/$ENV_ID/document -H "$AUTH" -o signed.pdf

Each sample sends agreement.pdf (tagged ^S1 in white text) to Jane Smith by text and email, checks its state, and downloads the signed PDF once it is completed. Set SIGLIO_API_KEY to your key. Node 18 or later, Python with requests, PHP with the curl extension, Ruby’s standard library. In production, add an Idempotency-Key header to the send.

The whole flow

One POST out, one webhook back

Your app sends the PDF and the signer. Siglio delivers the link, the signer signs on their phone or computer, and your webhook hears about it. Then you fetch the signed PDF.

Webhooks

The events, and a handler that checks the signature

Every account gets one webhook endpoint and every event type on it. Each delivery carries an X-Siglio-Signature header: t, a Unix time, and v1, the HMAC-SHA256 of t, a full stop and the raw body, keyed with your signing secret. Check it on the raw bytes before you trust the body.

EventFires when
envelope.deliveredThe signing link went out by text, email or both
envelope.viewedThe signer opened the document
envelope.partially_signedSigner one of two has signed. Not done yet
envelope.completedEveryone has signed. Download the signed PDF now
envelope.voidedYou voided it, or it expired unsigned after 30 days
envelope.paidA payment you asked for was recorded
envelope.attachments_receivedThe signer uploaded every file you asked for
A delivery · trimmed
{
  "id": "evt_8f3k2m9q1x",
  "type": "envelope.completed",
  "occurred_at": "2026-10-08T15:04:11.482Z",
  "data": {
    "envelope": {
      "id": "env_k7m2v9x3q1",
      "object": "envelope",
      "state": "completed",
      "document_name": "Service agreement",
      "delivery": "both",
      "signer": { "name": "Jane Smith", "email": "jane@example.com",
                  "phone": "+18135551212", "signed_at": "2026-10-08T15:04:09Z" },
      "completed_at": "2026-10-08T15:04:09Z"
    }
  }
}
// Node 18+, no dependencies. Saved as hook.mjs
import { createServer } from "node:http";
import crypto from "node:crypto";

createServer((req, res) => {
  let body = "";
  req.on("data", (c) => (body += c));
  req.on("end", () => {
    const [, t, v1] = /^t=(\d+),v1=([0-9a-f]+)$/.exec(req.headers["x-siglio-signature"] || "") || [];
    const mac = t && crypto.createHmac("sha256", process.env.SIGLIO_WEBHOOK_SECRET).update(`${t}.${body}`).digest("hex");
    const ok = mac && v1.length === mac.length && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(mac));
    if (!ok || Math.abs(Date.now() / 1000 - t) > 300) return res.writeHead(401).end();
    const event = JSON.parse(body);
    console.log(event.type, event.data.envelope?.id); // queue it, answer fast
    res.writeHead(200).end();
  });
}).listen(3000);

Both handlers reject a bad or missing signature, and anything signed more than five minutes ago, with 401. Answer 2xx fast and do the work from your own queue. Full details in the docs.

SDKs and tools

REST only, no SDK required

There is no official SDK. The API is JSON over HTTPS with a Bearer key, so the HTTP client your language already has is enough, as the samples above show.

Pricing

What it costs

WhatSiglio
Per envelope25¢
SMS deliveryIncluded, same 25¢
Monthly fee$0
Per seat$0
Minimum$0
Free trial25 documents free, no card

You are billed when an envelope is created, not when it is signed. A declined or ignored envelope still costs 25¢. E-signature API pricing in full.

Questions

The questions developers ask first

Is there a rate limit?

Yes: 120 requests a minute per API key, across all endpoints. Over it you get a 429 with a Retry-After header. Your 25 free documents use the same key and the same limit.

Do I need a different key when I start paying?

No. One key works from your first document. After the 25 free ones, add a card and your business details in the dashboard, and the same key keeps sending at 25¢ an envelope.

Which languages have official SDKs?

None, and none are needed: it is plain REST and JSON, so it works from any language. The OpenAPI spec will generate a client if you want one.

Can I test webhooks locally?

Yes. Your endpoint has to be an HTTPS URL, so expose your local port with a tunnel such as ngrok, save that URL in the dashboard, and press Send test: it posts a real signed webhook.test event to your handler.

How long are documents stored?

30 days after the envelope closes, then they are deleted. Download the signed PDF when envelope.completed arrives and keep your own copy.

Run the sample with your own key

One email address and your API key is on the next screen. No card, no sales call.

Continue with Google
or use your work email

25 documents free. No card needed.

Check your email

We sent a sign-in link to . It is good for 15 minutes, and your API key is waiting on the other side.