Version 1.13.1
Machine channel for Tvarka Sign: post a document and a list of signers.
With level: esign each signer reads the PDF and signs on the
Tvarka page, with no eID (simple e-signatures). With
level: qualified, the default, Tvarka runs its ordinary
qualified signing ceremony for each of them.
The signer follows the confirmation steps for their method
(signing confirmations). Or sign a hash or a PDF from your own
application with Smart-ID or Mobile-ID, with no hosted page
(headless signatures). A signature is always a
person using their own eID.
/v1/signings and MCP with level: esign. Each signer reads the PDF and signs on the Tvarka page; one charge per completed document (simple e-signatures)./v1/signings and MCP prepare documents, invite signers, track progress and return signed originals./v1/signatures lets your application show the verification code for Smart-ID or Mobile-ID, or a Smart-ID QR code or app link. It requires the workspace headless entitlement.For ADOC, each signer may set signingPurpose to signature (default), confirmation (approval), visa or registration. The accepted value is immutable and appears in the signed metadata and the invitation. Non-default purposes are rejected for PDF and ASiC-E; viewers cannot set a purpose. This is parallel signing of the container content and metadata, not creation of a registration record or a counter-signature over an earlier signature.
The OpenAPI below defines the supported public request fields. For hosted signing, CreateSigningRequest takes level: qualified (the default) or esign.
Send "level": "esign" to POST /v1/signings, or to
MCP send_document and request_signatures. Each signer
reads the PDF and signs on the Tvarka page, with no eID. One PDF per signing
(Office files and images are converted first), one or more signers, parallel
or sequential, link or email delivery. A signer has
email, name, language and one
authentication: email_link (default),
access_code with a code you give the signer
yourself, or sms with a phoneNumber when SMS codes
are switched on for your workspace. Tvarka keeps only a hash of the code and
never returns it.
{"level": "esign", "title": "Service agreement",
"document": {"fileToken": "<uploaded-file-token>"},
"signers": [{"email": "alex@example.com", "name": "Alex Example"},
{"email": "sam@example.com", "authentication": {"type": "access_code", "code": "<out-of-band-code>"}}],
"signingOrder": "sequential", "delivery": "link"}
The signers are fixed when the signing is created: to change them, cancel
and create a new one. Once everybody has signed, Tvarka seals the file with a
document timestamp; meanwhile the signing is pending with
processingStage: finalizing. When it is completed,
GET /v1/signings/{signingId}/document returns the sealed PDF and
GET /v1/signings/{signingId}/evidence the evidence ZIP (the
sealed PDF, the signing summary and the timestamp tokens). The signing names
its evidence.referenceCode and a public
verificationUrl. One charge per completed document, however
many signers; nothing is charged for a signing that does not complete.
Install n8n-nodes-tvarka-sign in self-hosted n8n through Settings → Community Nodes. Follow the maintained installation and credential guide and import the example workflow.
The connector uploads files, creates hosted qualified-signing requests, reads or lists them, downloads results, cancels requests and sends reminders. Use a Sign workspace key; DD and ATK keys are separate. It does not start headless signatures or the web application's simple e-signatures. Request creation is not signature completion.
The example needs your credentials and an uploaded file token. It explicitly sends email invitations, waits between status checks and downloads only after completion. Replace its example inputs before running; protect execution data and ceremony links. Existing sandbox keys simulate and return a sandbox-marked download. n8n Cloud installation requires n8n verification; npm publication alone does not establish Cloud availability.
Hosted and headless Smart-ID/Mobile-ID signing share the certificate lookup and signing sequence. A known signing certificate needs one signing PIN. Where the configured certificate service supplies the certificate without a PIN, first use also needs one signing PIN; a new Smart-ID account may first need approval in the app. If the flow instead needs a certificate-capture confirmation, that comes before the document-signing confirmation: two PINs in total. Follow the current verification code, rather than assuming a fixed number of prompts.
For headless signing, render nextAction: show verificationCode for compare_code, ask the signer to confirm their Smart-ID account for confirm_certificate, show qrLink as a QR code for scan_qr, open appLink for open_app, otherwise wait. A transition from authentication to signing can emit signature.confirmation_required with the new code and the same nextAction.revision; replace the displayed code. Hosted pages handle this for you. The Smart-ID QR/app-link journey opens the Smart-ID app for the signer; follow the hosted page and app prompts. Card/USB and NFC signing use the card's signing PIN through the supported local client; any required identity step is presented in that client.
REST quickstart · Webhook verification · Recent changes
GET /v1/signings - List signingsPOST /v1/signings - Create a signingGET /v1/signings/{signingId} - Get a signingPATCH /v1/signings/{signingId} - Update a live signing deadlineDELETE /v1/signings/{signingId} - Erase one signingPOST /v1/batches - Raise one signing per document for one set of partiesGET /v1/batches/{batchId} - Poll a batch and every signing in itPOST /v1/signings/{signingId}/archive - Raise the signed output to a long-term levelPOST /v1/files - Store a document once for reuse across signingsPOST /v1/conversions - Convert an Office file or image to PDF/A-2bGET /v1/files/{fileToken} - Inspect a stored fileDELETE /v1/files/{fileToken} - Purge a stored fileGET /v1/signings/{signingId}/comments - Read the notes on a signingPOST /v1/signings/{signingId}/comments - Add a note to a signingPOST /v1/erasure - Erase terminal signings in bulkPOST /v1/signings/{signingId}/cancel - Cancel a signingGET /v1/signings/{signingId}/document - Download the signed documentGET /v1/signings/{signingId}/evidence - Download the evidence of a simple e-signaturePOST /v1/signings/{signingId}/signers - Add a signer to a live signingPATCH /v1/signings/{signingId}/signers/{signerId} - Update a pending signer's allowed methodsDELETE /v1/signings/{signingId}/signers/{signerId} - Remove a pending signerPOST /v1/signings/{signingId}/signers/{signerId}/remind - Remind one signerPOST /v1/signings/{signingId}/simulate - Drive a sandbox signing to an outcomeGET /v1/me - Who the key acts forGET /v1/webhooks - List webhook subscriptionsPOST /v1/webhooks - Subscribe a URL to signing eventsGET /v1/webhooks/{webhookId} - Get a webhook subscriptionDELETE /v1/webhooks/{webhookId} - UnsubscribePOST /v1/signatures - Start a headless signatureGET /v1/signatures/{signatureId} - State, current step and code, resultPOST /v1/signatures/{signatureId}/cancel - Cancel a pending signatureGET /v1/signatures/{signatureId}/document - Download the signed artifactPOST /v1/signatures/{signatureId}/simulate - Drive a sandbox signature to an outcomeTvarka Sign 1.12.0, Streamable HTTP at
/mcp, registry name pro.tvarka/sign. Documents
come from the workspace vault, Markdown text, a link, a chat attachment or
base64.
send_document - Send a document (an envelope) for qualified electronic signature. Give the document exactly one way: markdown (Tvarka renders it to an A4 PDF; the first "# " heading becomes the title), pdfUrl (a public HTTPS link), pdfBase64, file (a file the user attached in the chat), or documentId (a document already in the vault). Each signer gets an email invitation and signs with their eID. Set senderSigns to have the connected person sign first. Returns the signingId and each signer's status. Billed per signature on completion.create_document - Render Markdown text to an A4 PDF and save it in the workspace vault without sending it. Returns a documentId for send_document and a previewUrl (valid for one hour) the user can open to check it.list_documents - Documents in the tenant workspace vault that can be sent for signing. Returns documentId values for send_document.request_signatures - Open a qualified signing ceremony on a vault document for one or more signers. Returns a ceremony URL per signer, or emails them directly when delivery is "email". Any workspace may use per-signer visibleSignature; the order snapshots shared workspace branding. Billed per signature on completion. send_document does the same and also takes markdown, links and files.get_signing - The current state of one signing and each of its signers. Once completed, signedDocumentUrl downloads the signed document (valid for one hour).list_signings - Signings raised through this connection or key, newest first.add_signer - Add one more signer to a pending signing. In a sequential signing they sign last.remind_signer - Re-send one signer their invitation email. Limited to one reminder per signer per hour.cancel_signing - Retract every outstanding invitation and close the signing. Signatures already collected are untouched and remain valid.Connect Tvarka Sign to your assistant once; then ask it to send a document
for signature, track it and fetch the signed original. Server URL:
https://sign-api.tvarka.pro/mcp. The assistant opens a Tvarka page,
you confirm with your eID, choose the company and allow the connection. It then
acts as you, with your rights in that company, and signatures are billed to the
company as usual. No key is pasted anywhere.
"httpUrl": "https://sign-api.tvarka.pro/mcp"). Gemini
Enterprise takes a fixed client: register one with
POST /oauth/register, redirect URI
https://vertexaisearch.cloud.google.com/oauth-redirect and
"token_endpoint_auth_method": "client_secret_post", then enter
the returned client ID and secret with authorization URL
https://sign-api.tvarka.pro/oauth/authorize and token URL
https://sign-api.tvarka.pro/oauth/token.Authorization: Bearer <key>
with your API key.What the assistant can do: write the document as text and have Tvarka render it to PDF/A, send a PDF from a link or a chat attachment, add you as the first signer, set a signing order and deadlines, remind, add signers, cancel, and hand you a download link for the signed document. It never signs: every signature is a person with their own eID. Connections are listed, with last use, under Settings, API settings, Connected apps, and end with one click.
credentials.json and README.txt, including the API key and
webhook secret. Its password is the last four digits of the employee's personal code
(asmens kodas), including leading zeroes. Open it with 7-Zip or Keka.
Credentials are never included in the email body. The key remains available in Settings.Show and Copy need no additional eID check. Only the owner can reveal a key. Existing production integrations keep their keys and signing history. For a historical hash-only key, Settings explains that Show/Copy prepares a recoverable companion on that same integration, leaving the original key valid. A deliberately revoked key is never silently recreated. Manage key retains advanced controls and existing sandbox integrations. Sandbox is retired from ordinary onboarding; existing sandbox keys continue working.
Send Authorization: Bearer <key> for REST and MCP.
tsk_live_ selects production; tsk_test_ selects sandbox.
The key acts as the named employee in the selected company workspace. Keep it
in your application's secret store. Sandbox simulation needs no funding.
Company and billing. Each key stays bound to one company workspace; changing the company selected in your browser does not move the key, its documents, charges or prepaid balance. The same user can hold separate keys for several companies. Check the company name and code beside the key in Settings and in the downloaded credentials. Personal signing is a separate context and does not change an API key's company.
The workspace manager or an active full-rights representative administers company API access;
a limited managing-employee role does not grant company administration. Full-rights
representatives can also invite other representatives and set up billing. Restricted
members can open Billing to see the required steps without seeing financial data. A payment-required response identifies
the key's company in billingContext; canManageBilling describes
the key owner's permission. If false, ask a company administrator to open
recoveryUrl after signing in and resolve the payment issue.
Users and access shows Change rights, Send API key and API settings directly in each user row; there is no More menu. Suspension and removal also have visible actions. API settings contains rotation and revocation for each existing integration.
Removing the employee's company role permanently revokes their API access; restoring the role does not restore old keys. Suspended access blocks API use. User and credential management remain available during a billing soft lock, while normal document operations retain their billing checks. ATK and Due Diligence use their own credentials and onboarding; Sign API keys do not grant access to those APIs.
PDF; appendable ASiC-E containers (.asice, .sce,
.bdoc); and the ADOC family (.adoc,
.bedoc, .cedoc, .gedoc,
.ggedoc) to countersign one that is already signed. A container
is signed in place, never converted. MDOC is not accepted for countersigning:
its composer writes a first signature only.
Since v1.9.0, Office files and images (.docx, .doc,
.odt, .rtf, .xlsx, .xls,
.ods, .pptx, .odp, .txt,
.jpg, .jpeg, .png) are converted to PDF/A-2b
before signing, including file uploads and URL intake. The resulting PDF is signed;
the original is not retained. POST /v1/conversions returns just the PDF,
without storing or signing it. Conversion has no additional charge and uses Tvarka's
conversion service. An unreadable file returns 422; unavailable conversion returns 503.
Instead of one finished file you can send container and have
several files composed into a new package that is signed once:
asice takes PDFs, adoc takes .pdf and
.xlsx, first file is the main document, up to 20 files.
document and container are mutually exclusive.
A PDF may set flatten: true to freeze its form fields into
page content before signing. It fails closed: if any field has no appearance
Tvarka can draw faithfully, nothing is flattened and the response names those
fields, because a signed document that does not show what the signer approved
is worse than a refused request. Flattening allows up to 1,000 pages, 5,000
widgets, 10,000 annotations and 10,000 field-tree nodes, with field depth up
to 64. These limits are shared across a batch. A cooperative 20-second
processing budget stops work between PDF operations; it cannot interrupt an
individual parser or writer call. A refusal returns HTTP 400 with a
flatten error pointer. Split the batch or flatten before upload.
Exact PDF placement is included for every workspace, in Tvarka Sign and the API. A company logo in the stamp is a premium feature that Tvarka activates. VIP whitelabel is a separate premium feature for changing or removing the vendor line. Standard clients keep the default Tvarka line; the Tekstas po parašu controls are hidden without VIP access. Contact info@tvarka.pro for activation.
The active company Vadovas opens Users and access → Parašo išvaizda in the cloud browser. Choose the company workspace, upload its logo, preview, then save. The tab remains visible with disabled controls until activation, even when the developer API is disabled. Tvarka operators manage the logo and VIP entitlements in Administravimas → Funkcijos; a customer cannot activate either entitlement themselves.
These are browser settings, not new bearer-key REST endpoints or MCP tools. Do not add logo, tagline or entitlement fields to signing requests.
Add visibleSignature to each signing party. Choose exactly one
of these signer objects (replace the sample email). A headless
pades signature takes the same object, or true for
the default corner, at the top level of POST /v1/signatures.
{
"email": "signer@example.com",
"visibleSignature": {"page": 1, "x": 36, "y": 36, "width": 148, "height": 52}
}
{
"email": "signer@example.com",
"visibleSignature": {"field": "Sig_Vadovas"}
}
page is 1-based. Coordinates are PDF points (1/72 inch),
offset from the unrotated page MediaBox's lower-left corner. Width is at least
148 pt and height at least 52 pt; all numbers must be finite. The rectangle
must fit both MediaBox and CropBox. Placement requires /UserUnit: 1.document.flatten: true.POST /v1/signings,
POST /v1/signings/{signingId}/signers,
POST /v1/batches and MCP request_signatures.
Batch placement must be valid for every document before invitations are sent.Each API order freezes its effective logo and vendor line on acceptance, including later signers, retries and idempotent replays. Editing or resetting workspace branding, or revoking logo/VIP access, does not change that snapshot. After VIP revocation, new snapshots use the default Tvarka line.
Regular Sign uses the same workspace branding for remote, USB/NFC and invited signing. Its Mano parašo vieta editor lets a user preview and save their own qualified PDF signature's coordinates or existing field; API-owned placement remains controlled by the API order. Sign freezes branding when signing, pairing, an internal-signature job or an invitation first begins; signed outputs retain the source snapshot. Internal electronic signatures keep their non-qualified label and existing overlay position. Personal signing and non-PDF containers retain their existing behavior.
Sandbox /simulate completion renders the requested placements
and snapshotted branding, including default-corner signers, branding-only orders
and MCP orders from vault documents. The artifact is conspicuously unsigned.
Already-signed input stays byte-identical and receives no stamp preview.
400 validation-failed: invalid placement, geometry, field or
flatten combination; use the returned JSON pointers to correct the request.422 stamp-preparation-failed: a sandbox preview cannot be prepared.signing.signer_failed and
signing.failed. Remaining invitations and pending work are retracted;
already collected signatures remain intact. A provider outage alone does not
trigger this stamp-failure cleanup.Send the signer to their ceremonyUrl in the current browser tab.
Add returnUrl and a random, session-bound returnState
(16-128 URL-safe ASCII characters) when creating the signing or batch.
Contact Tvarka to register your exact HTTPS return URL for your API client first.
After signing or declining, the browser returns automatically with
state, signingId, signerId and
result. Results are signed, declined,
cancelled, expired, simulated (sandbox),
or returned when the signer chooses Return to your application.
Returning early leaves the signing request open. Match state to the browser session
and retrieve the signing through your backend or verify its webhook; URL parameters
are never proof of a signature. One signer's completion need not complete the order.
The hosted page retains its anti-framing protection. An iframe allows the surrounding page to overlay signing controls; same-tab navigation keeps document review in Tvarka.
Signers are parallel by default. signingOrder: sequential
releases them one at a time in the order you posted them, and the signers who
are waiting hold a link that answers 404 until their turn, so the order is
enforced and not merely unsent. A decline stops the workflow at the
decliner's turn: the signing settles declined and the signers
still waiting are cancelled. A signer added to a sequential signing joins
the end of the queue. A signer may carry
role: viewer: a recorded party who is never invited, never blocks
completion and is sent nothing - you hold the webhook and the download.
Two deadlines. expiresInDays is the hard one, the date the
signing dies. softDeadlineInDays is the date it is wanted by:
nothing expires, but every signer who can still sign is reminded once on the
day it passes.
Upload documents up to 100 MB (100,000,000 bytes) with multipart
POST /v1/files: one binary part named file, retaining
its filename extension. Use the returned fileToken in
document.fileToken. Existing JSON/base64 uploads remain available
up to 15 MiB decoded. Signed outputs may grow as signature evidence is added.
POST /v1/files stores a document once and returns a
fileToken a later signing may reference instead of carrying
base64 again. The bytes are copied into each signing, so deleting a file
never reaches into one that already used it.
POST /v1/batches raises one signing per document for one set
of parties. It is a grouping, not a single signing act: every document keeps
its own ceremony and its own signature, because the ID card produces one
signature per document. It buys one call and one identifier to poll, not one
PIN for many documents. Combined source bytes and combined prepared bytes
each have a 100,000,000-byte limit. Repeated file tokens count repeatedly.
Known oversized batches are refused before reading stored files; remote
downloads and stored-file reads use the remaining source-byte allowance.
Aggregate overflow returns HTTP 413; remote-download refusals return HTTP 400
with the document URL pointer. No signing is created on refusal.
POST /v1/signings/{signingId}/comments keeps your own notes
on a signing. Comments are not shown to signers.
POST /v1/erasure erases terminal signings and headless signature
files in pages. Set limit from 1 to 100 (default 20), and optionally
before to an ISO datetime. While hasMore is true, pass
nextCursor as the next request's cursor. The cursor
keeps the same client and cutoff; omit before on continuation or
keep its original value. A page finishes its current resource and returns
after ten seconds of processing; an individual storage call still has its
own timeout. failedResources identifies failures, which remain
retryable. Finish the pages, then retry without a cursor to revisit failures.
hasMore: false ends the traversal; it does not mean failures were
erased. In-flight signings and pre-existing shared vault documents remain intact.
POST /v1/signings/{signingId}/archive raises signed output
to a long-term level: PDF to PAdES-B-LT, ASiC-E to XAdES-LT, embedding the
chain and revocation evidence so the signature still validates once the
certificate has expired. ASiC-E signing already reaches XAdES-LT on its own,
so this is for output that arrived at T. ADOC is refused by name: ADOC-V1.0
specifies XAdES-T and its validators expect it.
RFC 9457 problem documents, and request-body validation collects rather
than failing fast: a body with three bad fields comes back once, as
validation-failed, with an errors array of
{"pointer": "/signers/0/email", "detail": "..."}. The pointer is
an RFC 6901 JSON Pointer into what you sent, so a fault maps back to an input
without parsing prose.
A temporary webhook-address lookup failure returns
503 callback-resolution-unavailable with Retry-After.
Wait, then retry the same request with the same idempotency key. This refusal
happens before resource creation. An ambiguous setup failure still requires
reconciliation; keep its key and contact support.
A tsk_test_ key drives the whole lifecycle, including
POST /v1/signings/{signingId}/simulate. A simulated completion
returns a real downloadable file, so your download, hashing and storage code
runs for real without a card in anyone's hand. The sandbox never adds a
signature: an unsigned PDF comes back as your own pages with a banner saying
it is not signed, and anything posted already signed comes back
byte-identical, because those signatures are somebody else's and are not ours
to disturb. Every artifact is flagged sandbox in the response, the
webhook and an X-Tvarka-Sandbox header. Tvarka issues no test
signatures.
Use a POSIX shell with curl, jq and Python 3. Set TVARKA_SIGN_KEY in your local environment to an existing tsk_test_ key. Ordinary self-service onboarding creates production access; if you have no sandbox integration, request test access from info@tvarka.pro. Sign, Due Diligence and ATK keys are separate.
Use a small synthetic unsigned PDF named example.pdf. This flow uploads it, creates a link-delivered request without sending an invitation email, simulates completion, polls and verifies the downloaded artifact. For a simple e-signature, add "level": "esign" to create.json. The signers then read and sign on the Tvarka page with no eID (simple e-signatures). Run each create step once; retain its JSON body, key and returned ID before retrying.
set -eu
# Use an existing sandbox key. Never put a production key in this example.
case "$TVARKA_SIGN_KEY" in tsk_test_*) ;; *) echo "Use a sandbox key"; exit 1;; esac
BASE=https://sign-api.tvarka.pro
# Save any small, unsigned PDF as example.pdf before running this block.
# Keep this idempotency key and create.json for a retry of THIS signing.
IDEMPOTENCY_KEY="quickstart-$(python3 -c 'import uuid; print(uuid.uuid4())')"
TOKEN=$(curl --fail-with-body -sS "$BASE/v1/files" \
-H "Authorization: Bearer $TVARKA_SIGN_KEY" \
-F 'file=@example.pdf;type=application/pdf' | jq -er '.fileToken')
jq -n --arg token "$TOKEN" '{title:"Sandbox example",document:{fileToken:$token},delivery:"link",signers:[{email:"reader@example.test",name:"Example Reader",language:"en"}]}' > create.json
curl --fail-with-body -sS "$BASE/v1/signings" \
-H "Authorization: Bearer $TVARKA_SIGN_KEY" -H 'Content-Type: application/json' \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" --data-binary @create.json > signing.json
SIGNING=$(jq -er '.signingId' signing.json)
curl --fail-with-body -sS "$BASE/v1/signings/$SIGNING/simulate" \
-H "Authorization: Bearer $TVARKA_SIGN_KEY" -H 'Content-Type: application/json' \
-d '{"action":"complete"}' > simulated.json
curl --fail-with-body -sS "$BASE/v1/signings/$SIGNING" \
-H "Authorization: Bearer $TVARKA_SIGN_KEY" > result.json
jq -e '.status == "completed" and .completionMode == "sandbox_simulation" and .document.sandbox == true and .document.signed == false' result.json
curl --fail-with-body -sS "$BASE/v1/signings/$SIGNING/document" \
-H "Authorization: Bearer $TVARKA_SIGN_KEY" -D artifact.headers -o sandbox-result.pdf
python3 - <<'PY'
import hashlib, json
from pathlib import Path
result = json.loads(Path('result.json').read_text())
assert 'x-tvarka-sandbox: simulated-artifact-no-signature' in Path('artifact.headers').read_text().lower()
assert hashlib.sha256(Path('sandbox-result.pdf').read_bytes()).hexdigest() == result['document']['sha256']
print('Downloaded sandbox artifact; hash matches. No signature was created.')
PY
Multipart upload accepts up to 100,000,000 bytes; inline/base64 requests accept up to 15 MiB of decoded document bytes. Reuse fileToken for large files. Sandbox completion exercises the lifecycle and download path; it creates no qualified signature. Production uses the real signer ceremony instead of /simulate.
Using the same sandbox environment, this example supplies a synthetic identity and digest. In production, hash the exact document and display the corresponding content to the signer; renderHash records what you showed. Production headless signing needs an enabled workspace and the headless addendum.
# Sandbox only; set HEADLESS_REQUEST_KEY once and retain it for retries.
HEADLESS_REQUEST_KEY="headless-$(python3 -c 'import uuid; print(uuid.uuid4())')"
DIGEST=$(python3 -c 'import hashlib,base64; print(base64.b64encode(hashlib.sha256(b"Synthetic document").digest()).decode())')
jq -n --arg hash "$DIGEST" '{method:"smart_id",signer:{personalCode:"39001010011"},document:{name:"Synthetic document",profile:"cades-detached",hash:{algorithm:"sha256",value:$hash}},display:{text:"Sandbox signing"},renderHash:{algorithm:"sha256",value:$hash}}' > headless.json
curl --fail-with-body -sS "$BASE/v1/signatures" \
-H "Authorization: Bearer $TVARKA_SIGN_KEY" -H 'Content-Type: application/json' \
-H "Idempotency-Key: $HEADLESS_REQUEST_KEY" --data-binary @headless.json > signature.json
SIGNATURE=$(jq -er '.id' signature.json)
curl --fail-with-body -sS "$BASE/v1/signatures/$SIGNATURE/simulate" \
-H "Authorization: Bearer $TVARKA_SIGN_KEY" -H 'Content-Type: application/json' \
-d '{"action":"sign"}'
curl --fail-with-body -sS "$BASE/v1/signatures/$SIGNATURE" \
-H "Authorization: Bearer $TVARKA_SIGN_KEY"
Set a public HTTPS webhookUrl when creating a signing. Verify X-Tvarka-Signature-V2 against the raw body with your integration's webhook secret. V2 authenticates the attempt timestamp as well as the body. The older X-Tvarka-Signature is a body-only HMAC retained for existing consumers.
import hashlib
import hmac
import time
def verify_tvarka_webhook(raw_body: bytes, signature_v2: str, secret: str) -> bool:
# Call before parsing JSON. Pass the exact request bytes and the integration's
# webhook secret, not its API key. Keep the server clock synchronized.
try:
fields = dict(part.split('=', 1) for part in signature_v2.split(','))
timestamp = fields['t']
if abs(time.time() - int(timestamp)) > 300:
return False
expected = hmac.new(secret.encode('utf-8'),
timestamp.encode('ascii') + b'.' + raw_body,
hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, fields['v1'])
except (ValueError, KeyError, UnicodeError):
return False
After verification, parse the JSON and check the signing ID against your own records. Process each event once: use an atomic durable record keyed by the authenticated payload's signing/signature ID, event type and optional signer ID; the supplied X-Tvarka-Idempotency-Key is also stable across retries. Acknowledge with 2xx after durable acceptance, then process asynchronously. Redeliveries may arrive, and polling remains available.
Automation platforms register their own callback URL: POST /v1/webhooks with url and events answers 201 with a Location header, and DELETE on that location turns it off. The subscription receives the chosen events of every signing this integration creates, signed with the same webhook secret. Each delivery carries eventId (the idempotency key), webhookId and the whole signing, without ceremony links. Answer 410 to remove a subscription from the receiving side. GET /v1/me tests a key and names its workspace; the key may also be sent as X-Api-Key.
Idempotency-Key. After an uncertain response or pending 409, reconcile the original operation before creating another. Do not solve a timeout by minting a new key.Retry-After. Stop automatic retries for invalid input, authentication and billing refusals until corrected. Reconcile a timed-out mutation before repeating it.Retry-After. A failed webhook does not cancel the signing; poll its state./v1/webhooks) for automation platforms, GET /v1/me, the externalId filter on GET /v1/signings and the X-Api-Key header.level: esign) with per-signer authentication, processingStage and GET /v1/signings/{signingId}/evidence; headless nextAction, Smart-ID QR code and app link (interaction) and the initiation_unknown outcome.POST /v1/conversions and conversion during document intake.pades profile.POST /v1/signatures signs one document for one signer with
Smart-ID or Mobile-ID, with no hosted page, no invitation and no email. Your
application shows the verification code and the signer confirms on their
phone. The confirmation sequence depends on the
known certificate and configured certificate service. When an identity step
comes first, the document-signing step follows with a new code: step
moves from authentication to signing and a
signature.confirmation_required webhook carries the new code.
Name a profile: cades-detached signs your SHA-256 hash and
returns a detached .p7s at CAdES-BASELINE-LT, with the
certificate chains and revocation data embedded;
pades signs a PDF, such as the PDF/A-2 that ESPBI renders, and
returns it signed at PAdES-BASELINE-LT, added in an incremental update. A
visible stamp is your choice, as in Tvarka Sign: the signer's name from the
signing certificate and the signing time, with the workspace logo where it
has one. Send "visibleSignature": true for the default corner,
or an object with exact coordinates or an existing empty signature field, in
the same shape as for a hosted signer. Without it the signature stays
invisible. The stamp speaks the
language of your company's country; a company outside Lithuania gets the
Tvarka.eu stamp. Send renderHash, the digest of what you
showed the signer; it is kept as evidence with the display text, the input
digest, the codes and the signing certificate. Production workspaces are
enabled by Tvarka after the headless addendum is signed. One signature is
billed on success; declined, expired, failed and cancelled ones are free.
For many documents at once, sign in bulk with the ID card through the ATK
API.
Smart-ID by QR code or app link: send "interaction": {"type": "qr"}
or {"type": "app_link"} (Smart-ID only). No personal code is
needed; an optional Lithuanian signer.personalCode accepts only
that person. Show nextAction.qrLink as a QR code and fetch a
fresh one every second. app_link needs a registered
returnUrl and a returnState; the Smart-ID app brings
the signer back to it with state and signatureId.
Check that state belongs to the browser that started; the result
itself comes only from polling or the webhook.
A start that may have reached the signer's phone without an answer is never
sent again: the signature fails as initiation_unknown and is not
billed. Ask the signer to dismiss any prompt and retry after two minutes. A
503 with Retry-After means nothing started: retry
with the same Idempotency-Key.
This orchestration API offers LT ATK card signing over NFC in the Tvarka Sign mobile app, plus Smart-ID and Mobile-ID. The separate ATK API is the full low-level LT ATK surface for NFC, USB/readers and raw signatures. Across Tvarka APIs, PAdES, XAdES, CAdES, JAdES and ASiC cover all Regulation (EU) 2026/248 Annex I families.
Validate electronic signatures and retrieve advisory validation results for integration into your document workflows.
Signatures are billed to your Tvarka Sign workspace on the ordinary per-signature price ladder. There is no separate API tariff. Kiek naudojate, tiek ir mokate. Jokių prenumeratų.
Simple e-signature: 0.19 EUR per completed document, excluding VAT, however many signers.
| Monthly QES count | Smart-ID / Mobile-ID / LT ID | ID card / USB token |
|---|---|---|
| 1-499 | EUR 0.19 | EUR 0.13 |
| 500-999 | EUR 0.18 | EUR 0.10 |
| 1000-1999 | EUR 0.17 | EUR 0.08 |
| 2000+ | EUR 0.16 | EUR 0.06 |
The qualified timestamp is included. The company's monthly QES count sets one price for every QES of that month; an individually agreed tariff takes precedence. Sandbox is free. Full pricing and allowances. A company outside Lithuania reads tvarka.eu pricing.
Questions: info@tvarka.pro