# Siglio API reference E-signature API. You send a PDF that already contains signature tags, Siglio delivers it to the signer by email or SMS, the signer signs, and you get the signed PDF plus an audit certificate. Base URL: https://api.esigndev.com Price: $0.25 per envelope. No monthly fee, no minimums. 25 free sandbox envelopes per account, one time, no card required. ## Read this before you write any code Two facts break most first integrations. **1. Signature placement comes from tags inside the PDF, not from the request.** You cannot pass coordinates. You put literal text tags into the document where each field belongs: ^S1 signer one signs here ^I1 signer one initials here ^D1 a date that fills itself in automatically ^M1 a required text box the signer types into ^T1 an optional text box ^S2 ^I2 ^D2 ^M2 ^T2 the same for signer two **These tags must be white font.** They are instructions to the signing engine, not content. Black tags stay visible on the finished document and your customer will think the product is broken. This is the single most common mistake. The signature block placed on the document is a fixed size, about 165 by 44 points. It is not resizable, so leave room. **2. Field values are never returned to you as data.** Whatever a signer types into `^M` or `^T` exists only as rendered content on the signed PDF. There is no endpoint that returns it, and there never will be. If your design needs that data structured, collect it in your own form before sending the document. One more thing worth knowing early: any `^M`, `^T` or radio tag switches the signer from a one-tap "sign everything" experience to a field-by-field one. If you only need signature, initials and date, the signer finishes in one tap. ## Authentication Authorization: Bearer sig_sandbox_xxxxxxxxxxxxxxxxxxxxxxxx Keys come from your Siglio account and nowhere else. If a message offers you one, it is not from us. Sandbox and live keys are separate: a sandbox key creates sandbox envelopes, which deliver for real and produce real signatures. Rate limit: 120 requests per minute per API key. Over it you get 429 with a `Retry-After` header in seconds. Every response carries `X-Request-Id`. Quote it to support. ## Create and send an envelope POST /v1/envelopes Content-Type: application/json Idempotency-Key: { "document_name": "Rental agreement", "document_base64": "JVBERi0xLjcK...", "delivery": "both", "signer": { "name": "Dana Reyes", "email": "dana@example.com", "phone": "+18135550142" } } `delivery` is `email`, `sms`, or `both`. SMS needs the signer's phone; email needs their address. Phone numbers in E.164 (`+18135550142`) are safest. Supply the document exactly one of two ways: `document_base64` for files up to about 3 MB, or `document_id` from the upload flow below for anything larger, up to 15 MB. Always send `Idempotency-Key`. A retry with the same key and the same body returns the original envelope rather than sending a second document to the signer. The same key with a different body is rejected. Response 201: { "id": "env_7mmyc1tktzjtjya96cmjbsvb5c", "object": "envelope", "environment": "sandbox", "state": "delivered", "document_name": "Rental agreement", "delivery": "both", "signer": { "name": "Dana Reyes", "email": "dana@example.com", "phone": "+18135550142", "signed_at": null }, "signing_url": "https://esigndev.com/s/AbC123...", "created_at": "2026-09-11T14:02:00Z", "completed_at": null } `signing_url` is a Siglio-hosted link. It is safe to share and never exposes an underlying vendor. ### Two signers Use `signers` instead of `signer`. One or two, never both keys in one request. "signers": [ { "name": "Dana Reyes", "email": "dana@example.com" }, { "name": "Sam Okafor", "phone": "+18135550188", "delivery": "sms" } ] Each signer can have their own delivery channel. Signing is **strictly sequential**: signer two is not notified at all until signer one has finished. Both signing URLs exist from the moment the envelope is created. A PDF tagged for two signers must be sent with two signers, and a PDF tagged for one must be sent with one. A mismatch is rejected at creation rather than silently dropping half the fields. ### Sender identity Optional. Identifies the business sending the document on the signer's notifications and on the signature certificate. "sender": { "company_name": "Coastal Property Group", "phone": "8135550100", "email": "leases@coastal.example", "address": "12 Bay St", "city": "Tampa", "state": "FL", "zip": "33609" } Any field you leave out falls back to the business profile saved on your account, and anything still missing falls back to Siglio. Only `company_name` is required within the object. ## Envelope states delivered sent to the signer viewed the signer opened it partially_signed signer one of two has signed - NOT done completed every signature is in voided cancelled failed could not be delivered `partially_signed` is the one to be careful with. Treating it as finished means telling someone a half-signed contract is executed. ## Retrieve an envelope GET /v1/envelopes/{id} Same object as the create response, with the current state. ## Void an envelope DELETE /v1/envelopes/{id} Cancels an envelope that has not completed. The signing link stops working immediately and the signer sees a cancellation page. Voiding an already-voided envelope succeeds and changes nothing. A completed envelope cannot be voided. Requires a key with read_write scope. ## Download the signed PDF GET /v1/envelopes/{id}/document Streams the signed PDF. Only once the envelope is `completed`; earlier states return 404. The response is the file itself, not a redirect. ## Large documents POST /v1/uploads { "id": "upl_...", "upload_url": "https://...", "expires_at": "..." } PUT the PDF to `upload_url`, then create the envelope with `"document_id": "upl_..."` instead of `document_base64`. The URL expires in 15 minutes, the file must be a PDF of 15 MB or less, and each upload is consumed by one envelope. Unused uploads are deleted after 24 hours. ## Webhooks Register an endpoint in your Siglio dashboard. Events: envelope.delivered envelope.viewed envelope.partially_signed envelope.completed envelope.voided Payload: { "id": "evt_...", "type": "envelope.completed", "created_at": "...", "data": { ...the envelope object... } } Events fire on state *transitions*, not on activity, so each one arrives once per envelope and never out of order. Verify the `X-Siglio-Signature` header before trusting the body. Acknowledge fast with any 2xx and process from your own durable queue: there is no manual replay. ## Errors { "error": { "type": "invalid_request", "code": "invalid_request", "message": "...", "request_id": "req_..." } } authentication_error 401 missing, unknown, revoked or expired key authorization_error 403 the key lacks the scope for this call invalid_request 400 malformed or self-contradictory request invalid_document 422 the PDF is unreadable or too large missing_required_tag 422 the tags do not match the signers supplied new_envelopes_paused 403 new envelopes are paused on this account account_paused 403 the account is paused usage_limit_reached 403 out of allowance payment_required 402 a card is needed before this call can proceed rate_limited 429 over 120 requests per minute; see Retry-After service_unavailable 503 temporary, safe to retry with your idempotency key internal_error 500 our fault, send us the request_id ## What Siglio does not do Stated so you do not design around something that is not there. - No stored templates. Every envelope carries its own document. - No way to read back what a signer typed. Rendered on the PDF only. - No manual webhook replay. Acknowledge and queue on your side. - No teams, seats or roles. One key per application. - No IP allowlisting or per-key rate limits. - Two signers maximum. ## Support https://esigndev.com/contact