Tvarka Sign API

Machine channel for Tvarka Sign: post a document and a list of signers and Tvarka runs its ordinary qualified signing ceremony for each of them on the hosted page or in the Tvarka Sign mobile app (LT ATK over NFC, Smart-ID, Mobile-ID). Nothing in the API signs anything - a signature is always a human act with the signer's own eID - so every operation is about getting a document in front of the right person and learning what they did. Orchestration sibling of the card-level ATK API; RFC 9457 problem details, HMAC-signed webhooks, and a hosted MCP server.

Operations 7

POST /sign/requests Create a signing request (server-to-server) #
POST /sign/{requestId}/certificate Submit the card's signing certificate; receive the DTBS #
POST /sign/{requestId}/complete Submit the raw card signature; assemble the container #
GET /sign/{requestId} Poll status + validation axis; fetch the result #
GET /sign/{requestId}/document Download the signed container #
POST /sign/{requestId}/cancel Cancel a non-terminal request #
GET /sign/{requestId}/pairing Rotate and return the NFC pairing token for a sign request #

Documentation

Specifications

Other Resources

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/tvarka-sign-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

tvarka-sign-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Tvarka ATK Sign API
  version: 1.4.0
  summary: Lithuanian eID authentication, qualified signing, validation and LTV services.
  description: 'The canonical ATK API contract. Authentication and signing are card-only: LT ATK physical-reader and NFC ceremonies, under one request, polling, webhook and metering model. Remote methods are not offered here - hosted remote-method ceremonies live in the Tvarka Sign developer API. Start with the five-minute quickstart or use the specialist authentication and signing references.'
  termsOfService: https://atk.tvarka.pro/docs/lifecycle/
  contact:
    name: Tvarka API team
    url: https://atk.tvarka.pro/docs/access/
    email: info@tvarka.pro
  license:
    name: Proprietary
    url: https://tvarka.pro/salygos/
servers:
- url: https://atk.tvarka.pro/v1
  description: 'Production. Sandbox runs on the same host - provider credentials issued with

    environment=sandbox get the identical API against test-card material and are never billed.

    '
security:
- basicAuth: []
tags:
- name: Sign
  description: The QES signing ceremony (`/v1/sign/*`).
paths:
  /sign/requests:
    post:
      tags:
      - Sign
      operationId: createSignRequest
      summary: Create a signing request (server-to-server)
      description: 'HTTP Basic. Provide the document one of three ways - inline `document` (base64), an allow-listed

        `documentRef`, or a bare `hash` (only for `format:"raw"`). Container formats

        (pades/asice/adoc) require exactly one of `document` or `documentRef`. PAdES accepts an unsigned

        or already-signed PDF; ASiC-E/ADOC accept either a PDF (Tvarka constructs a new single-payload

        container) or an existing valid container, which is treated as an opaque whole and receives one

        additional signature without payload or attachment edits. Physical requests return a client

        token; NFC returns a pairing hint.'
      x-codeSamples:
      - lang: curl
        label: Physical reader PAdES
        source: "curl -u \"$ATK_KEY_ID:$ATK_KEY_SECRET\" https://atk.tvarka.pro/v1/sign/requests \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"format\":\"pades\",\"method\":\"physical\",\"document\":\"<base64-pdf>\"}'\n"
      - lang: curl
        label: NFC phone tap PAdES
        source: "curl -u \"$ATK_KEY_ID:$ATK_KEY_SECRET\" https://atk.tvarka.pro/v1/sign/requests \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"format\":\"pades\",\"method\":\"nfc\",\"document\":\"<base64-pdf>\"}'\n"
      security:
      - basicAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SignSignRequestCreate'
            examples:
              physicalAtk:
                summary: Primary ATK PAdES method
                value:
                  format: pades
                  method: physical
                  document: JVBERi0xLjQK
              nfc:
                summary: ATK by NFC phone tap
                value:
                  format: pades
                  method: nfc
                  document: JVBERi0xLjQK
      responses:
        '202':
          description: Request created; awaiting the ATK client authorization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SignSignRequestCreated'
        '400':
          $ref: '#/components/responses/SignBadRequest'
        '401':
          $ref: '#/components/responses/SignUnauthorized'
        '403':
          $ref: '#/components/responses/SignForbidden'
        '413':
          $ref: '#/components/responses/SignTooLarge'
        '429':
          $ref: '#/components/responses/SignRateLimited'
        '503':
          $ref: '#/components/responses/SignServiceUnavailable'
  /sign/{requestId}/certificate:
    post:
      tags:
      - Sign
      operationId: submitSignCertificate
      summary: Submit the card's signing certificate; receive the DTBS
      description: 'Bearer clientToken. The API validates the certificate (chain, revocation, purpose =

        signing/content-commitment, qualified/QSCD evidence), prepares the format-specific DTBS (for

        PAdES - the SHA-256 CAdES SignedAttributes digest; SHA-256 for both key curves), and returns

        it + `operationToken`. Physical/NFC only.'
      security:
      - clientToken: []
      parameters:
      - $ref: '#/components/parameters/SignRequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SignSignCertificateSubmit'
      responses:
        '200':
          description: DTBS + operation token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SignSignCertificateChallenge'
        '401':
          $ref: '#/components/responses/SignUnauthorized'
        '403':
          $ref: '#/components/responses/SignForbidden'
        '404':
          $ref: '#/components/responses/SignNotFound'
        '409':
          $ref: '#/components/responses/SignConflict'
        '422':
          $ref: '#/components/responses/SignUnprocessable'
  /sign/{requestId}/complete:
    post:
      tags:
      - Sign
      operationId: completeSign
      summary: Submit the raw card signature; assemble the container
      description: 'Bearer clientToken + single-use `operationToken`. Synchronous: the API verifies the signature

        against the stored DTBS + cert, assembles + timestamps the AdES container inline, schedules

        async validation, and returns `200 done` with `validation:{status:"pending"}` (or

        `notApplicable` in sandbox/raw, or the internal ADOC verdict). `finalizing` is observable via

        GET only if a crash wedges the request until the reaper releases it. Retry-safe; a transient

        assembly failure returns a retryable 5xx with the operation released; one `atk.sign` charge

        at `done`.'
      security:
      - clientToken: []
      parameters:
      - $ref: '#/components/parameters/SignRequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SignSignCompleteSubmit'
      responses:
        '200':
          description: Done - container assembled + signature verified.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SignSignResult'
        '401':
          $ref: '#/components/responses/SignUnauthorized'
        '404':
          $ref: '#/components/responses/SignNotFound'
        '409':
          $ref: '#/components/responses/SignConflict'
        '422':
          $ref: '#/components/responses/SignUnprocessable'
  /sign/{requestId}:
    get:
      tags:
      - Sign
      operationId: getSignRequest
      summary: Poll status + validation axis; fetch the result
      security:
      - basicAuth: []
      - clientToken: []
      parameters:
      - $ref: '#/components/parameters/SignRequestId'
      responses:
        '200':
          description: Current state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SignSignRequestState'
        '401':
          $ref: '#/components/responses/SignUnauthorized'
        '404':
          $ref: '#/components/responses/SignNotFound'
  /sign/{requestId}/document:
    get:
      tags:
      - Sign
      operationId: downloadSignedDocument
      summary: Download the signed container
      description: Authorized by the provider's Basic credentials or a `downloadToken` query param.
      security:
      - basicAuth: []
      - downloadToken: []
      parameters:
      - $ref: '#/components/parameters/SignRequestId'
      responses:
        '200':
          description: The signed container bytes.
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        '401':
          $ref: '#/components/responses/SignUnauthorized'
        '404':
          $ref: '#/components/responses/SignNotFound'
  /sign/{requestId}/cancel:
    post:
      tags:
      - Sign
      operationId: cancelSignRequest
      summary: Cancel a non-terminal request
      security:
      - basicAuth: []
      - clientToken: []
      parameters:
      - $ref: '#/components/parameters/SignRequestId'
      responses:
        '200':
          description: Cancelled.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SignSignRequestState'
        '404':
          $ref: '#/components/responses/SignNotFound'
        '409':
          $ref: '#/components/responses/SignConflict'
  /sign/{requestId}/pairing:
    get:
      tags:
      - Sign
      operationId: getSignPairing
      summary: Rotate and return the NFC pairing token for a sign request
      security:
      - basicAuth: []
      parameters:
      - $ref: '#/components/parameters/SignRequestId'
      responses:
        '200':
          description: Newly rotated pairing token and links.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SignPairingInfo'
        '404':
          $ref: '#/components/responses/SignNotFound'
        '409':
          $ref: '#/components/responses/SignConflict'
components:
  schemas:
    SignErrorCode:
      type: string
      description: 'The full stable error-code catalog of the ATK API family (auth + sign + services);

        each endpoint returns the subset that applies to it. By HTTP status:

        400 invalid_json, missing_field, invalid_field, invalid_webhook_url, invalid_document_ref.

        401 invalid_basic_credentials, invalid_client_token, client_token_expired,

        operation_token_expired, invalid_download_token.

        403 origin_not_allowed, ip_not_allowed, format_not_allowed, document_ref_host_not_allowed,

        method_not_allowed, tenant_suspended, tier_forbidden.

        404 request_not_found, pairing_not_found, document_not_ready.

        409 request_terminal, operation_token_spent, identity_swap, idempotency_conflict,

        service_in_progress, pairing_not_available, pairing_already_claimed.

        410 pairing_expired. 413 document_too_large.

        422 cert_invalid, untrusted_chain, cert_revoked, cert_expired, not_qualified,

        cert_purpose_mismatch, signature_invalid, document_hash_mismatch, document_size_mismatch.

        429 rate_limited. 500 assembly_failed. 502 document_ref_fetch_failed.

        503 erasure_failed, pairing_service_unavailable, service_unavailable.

        The catalog can grow in minor versions - fall back to HTTP status semantics

        for codes you do not recognize.

        '
      enum:
      - invalid_json
      - missing_field
      - invalid_field
      - invalid_webhook_url
      - invalid_document_ref
      - invalid_basic_credentials
      - invalid_client_token
      - client_token_expired
      - operation_token_expired
      - invalid_download_token
      - origin_not_allowed
      - ip_not_allowed
      - format_not_allowed
      - document_ref_host_not_allowed
      - method_not_allowed
      - tenant_suspended
      - tier_forbidden
      - request_not_found
      - pairing_not_found
      - document_not_ready
      - request_terminal
      - operation_token_spent
      - identity_swap
      - idempotency_conflict
      - service_in_progress
      - pairing_not_available
      - pairing_already_claimed
      - pairing_expired
      - document_too_large
      - cert_invalid
      - untrusted_chain
      - cert_revoked
      - cert_expired
      - not_qualified
      - cert_purpose_mismatch
      - signature_invalid
      - document_hash_mismatch
      - document_size_mismatch
      - rate_limited
      - assembly_failed
      - document_ref_fetch_failed
      - erasure_failed
      - pairing_service_unavailable
      - service_unavailable
    SignSignRequestCreated:
      type: object
      required:
      - requestId
      - method
      - verificationCode
      - status
      - expiresAt
      description: Physical requests return `clientToken`; NFC returns `pairing`.
      properties:
        requestId:
          type: string
          format: uuid
        method:
          $ref: '#/components/schemas/SignMethod'
        verificationCode:
          type: string
          description: NFC anti-relay confirmation code.
        clientToken:
          type: string
        status:
          $ref: '#/components/schemas/SignStatus'
        expiresAt:
          type: string
          format: date-time
        pairing:
          allOf:
          - $ref: '#/components/schemas/SignPairingHint'
          description: Present only when method == nfc.
    SignSignCertificateChallenge:
      type: object
      required:
      - requestId
      - dtbs
      - dtbsHashAlgOid
      - operationToken
      - cert
      - signing
      properties:
        requestId:
          type: string
          format: uuid
        dtbs:
          type: string
          format: byte
          description: Base64 of the exact digest the card signs (e.g. for PAdES, the curve-matched digest of the CAdES SignedAttributes).
        dtbsHashAlgOid:
          $ref: '#/components/schemas/SignHashAlgOid'
        operationToken:
          type: string
        verificationCode:
          type: string
        cert:
          type: object
          properties:
            subject:
              $ref: '#/components/schemas/SignCertSubject'
        signing:
          type: object
          properties:
            format:
              $ref: '#/components/schemas/SignFormat'
            signatureEncodingHints:
              type: string
              description: Optional hint for how the card signature should be encoded before submission (P1363 vs DER).
    SignPairingInfo:
      allOf:
      - $ref: '#/components/schemas/SignPairingHint'
      - type: object
        required:
        - pairingToken
        - expiresAt
        properties:
          pairingToken:
            type: string
          expiresAt:
            type: string
            format: date-time
    SignValidation:
      type: object
      description: The advisory validation axis. Independent of `status`. See the two-axes note.
      required:
      - status
      properties:
        status:
          type: string
          enum:
          - pending
          - passed
          - failed
          - notApplicable
        level:
          type: string
          description: e.g. QUALIFIED_VALID, VALID_NOT_QUALIFIED, INDETERMINATE.
        report:
          type: string
          description: Optional pointer/id to the stored validation report.
    SignPairingHint:
      type: object
      properties:
        pairingUrl:
          type: string
          format: uri
          example: https://sign.tvarka.pro/atk-login/#PAIRING_TOKEN
        deepLink:
          type: string
          example: tvarkasign://atk/pair/PAIRING_TOKEN
        qrPayload:
          type: string
          example: https://sign.tvarka.pro/atk-login/#PAIRING_TOKEN
    SignMethod:
      type: string
      enum:
      - physical
      - nfc
      example: physical
      description: physical = desktop reader; nfc = phone tap.
    SignSignRequestState:
      type: object
      required:
      - requestId
      - method
      - status
      properties:
        requestId:
          type: string
          format: uuid
        method:
          $ref: '#/components/schemas/SignMethod'
        status:
          $ref: '#/components/schemas/SignStatus'
        validation:
          $ref: '#/components/schemas/SignValidation'
        cert:
          type: object
          properties:
            subject:
              $ref: '#/components/schemas/SignCertSubject'
        sig:
          type: string
          format: byte
        sigAlgOid:
          type: string
        downloadToken:
          type: string
        error:
          $ref: '#/components/schemas/SignErrorBody'
    SignSignRequestCreate:
      description: The ATK card signs every listed format, by physical reader or NFC.
      oneOf:
      - title: ATK raw detached CAdES
        type: object
        required:
        - format
        - method
        - hash
        - hashAlgOid
        additionalProperties: false
        properties:
          format:
            const: raw
          method:
            type: string
            enum:
            - physical
            - nfc
            example: physical
          hash:
            type: string
            format: byte
          hashAlgOid:
            $ref: '#/components/schemas/SignHashAlgOid'
          filename:
            type: string
          mimeType:
            type: string
          message:
            type: string
          externalId:
            type: string
          webhookUrl:
            type: string
            format: uri
      - title: ATK PDF or container
        type: object
        required:
        - format
        - method
        additionalProperties: false
        properties:
          format:
            enum:
            - pades
            - asice
            - adoc
          method:
            type: string
            enum:
            - physical
            - nfc
            example: physical
          document:
            type: string
            format: byte
          documentRef:
            $ref: '#/components/schemas/SignDocumentRef'
          filename:
            type: string
          mimeType:
            type: string
          message:
            type: string
          externalId:
            type: string
          webhookUrl:
            type: string
            format: uri
        oneOf:
        - required:
          - document
          properties:
            document: {}
        - required:
          - documentRef
          properties:
            documentRef: {}
    SignSignatureEncoding:
      type: string
      enum:
      - P1363
      - DER
      default: P1363
      description: Informational - the server auto-detects and accepts either encoding regardless of this field.
    SignSignCompleteSubmit:
      type: object
      required:
      - signature
      - signatureAlgorithm
      - operationToken
      properties:
        signature:
          type: string
          format: byte
          description: Base64 raw card signature over `dtbs` (QES key).
        signatureAlgorithm:
          $ref: '#/components/schemas/SignSignatureAlgorithm'
        signatureEncoding:
          $ref: '#/components/schemas/SignSignatureEncoding'
        operationToken:
          type: string
    SignFormat:
      type: string
      enum:
      - pades
      - asice
      - adoc
      - raw
      description: 'pades = signed PDF; asice/adoc = XAdES-T containers; raw = a detached CAdES package from

        a bare hash (no container returned). Container formats require `document` or `documentRef`.

        '
    SignDocumentRef:
      type: object
      description: 'Backend-fetched document. Hard SSRF controls apply - HTTPS only, host allow-list, no

        private/loopback/link-local, DNS-rebind protection, size cap enforced pre + mid stream, and the

        fetched bytes are verified against `sha256`. `authorization` is used only for the fetch, never

        logged or persisted.

        '
      required:
      - url
      - sha256
      - sizeBytes
      additionalProperties: false
      properties:
        url:
          type: string
          format: uri
          pattern: ^https://
        sha256:
          type: string
          pattern: ^[0-9a-fA-F]{64}$
        sizeBytes:
          type: integer
          minimum: 1
        authorization:
          type: string
          maxLength: 2048
    SignError:
      type: object
      required:
      - error
      properties:
        error:
          $ref: '#/components/schemas/SignErrorBody'
    SignStatus:
      type: string
      description: 'Non-terminal - pending/awaitingCard/awaitingCredentials/finalizing. Terminal success - done.

        Terminal failure - cancelled/timeout/deviceError/pinBlocked/cardRemoved/certInvalid.

        Validation failure is on the `validation` axis, NOT here.

        '
      enum:
      - pending
      - awaitingCard
      - awaitingCredentials
      - finalizing
      - done
      - cancelled
      - timeout
      - deviceError
      - pinBlocked
      - cardRemoved
      - certInvalid
    SignSignCertificateSubmit:
      type: object
      required:
      - certificate
      properties:
        certificate:
          type: string
          format: byte
          description: Base64 DER of the card's signing certificate.
    SignErrorBody:
      type: object
      required:
      - code
      - message
      properties:
        code:
          $ref: '#/components/schemas/SignErrorCode'
          description: 'Stable machine code. documentRef failures use `invalid_document_ref`,

            `document_ref_host_not_allowed`, `document_ref_fetch_failed`,

            `document_size_mismatch`, `document_hash_mismatch`, or `document_too_large`.

            '
        message:
          type: string
        requestId:
          type: string
          format: uuid
        retryable:
          type: boolean
    SignCertSubject:
      type: object
      properties:
        serialNumber:
          type: string
          example: PNOLT-39001010000
        givenName:
          type: string
        sn:
          type: string
        cn:
          type: string
        c:
          type: string
          example: LT
    SignSignatureAlgorithm:
      type: string
      enum:
      - ES256
      - ES384
    SignSignResult:
      type: object
      required:
      - status
      - method
      - validation
      - cert
      properties:
        status:
          type: string
          const: done
        method:
          $ref: '#/components/schemas/SignMethod'
        validation:
          $ref: '#/components/schemas/SignValidation'
        sig:
          type: string
          format: byte
          description: For `format:"raw"`, the detached signature package. Absent for container formats (download the container instead).
        sigAlgOid:
          type: string
        cert:
          type: object
          properties:
            subject:
              $ref: '#/components/schemas/SignCertSubject'
        downloadToken:
          type: string
          description: One-off token for GET /sign/{id}/document.
    SignHashAlgOid:
      type: string
      enum:
      - 2.16.840.1.101.3.4.2.1
      - 2.16.840.1.101.3.4.2.2
      description: SHA-256 / SHA-384 OID, curve-matched.
  responses:
    SignUnprocessable:
      description: Cert purpose/chain/revocation/qualified reject, dtbs mismatch, bad signature, doc hash mismatch.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SignError'
    SignNotFound:
      description: Unknown request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SignError'
    SignTooLarge:
      description: Document exceeds the tenant's max size.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SignError'
    SignRateLimited:
      description: Too many requests.
      headers:
        Retry-After:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SignError'
    SignForbidden:
      description: Format not allowed / origin not allowed / tenant suspended.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SignError'
    SignServiceUnavailable:
      description: Validation/TSA/revocation dependency failed transiently; retry with the same Idempotency-Key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SignError'
    SignBadRequest:
      description: Malformed input (e.g. container format without document, hash without raw).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SignError'
    SignUnauthorized:
      description: Missing/invalid credentials or client token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SignError'
    SignConflict:
      description: Spent operation token, identity swap, terminal request, or idempotency conflict/in-progress operation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SignError'
  parameters:
    SignRequestId:
      name: requestId
      in: path
      required: true
      schema:
        type: string
        format: uuid
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: 'Provider server-to-server credentials `keyId:keySecret`. Server-to-server only, also gated by the

        provider''s server IP allow-list. Never placed in a browser/mobile client.

        '
    clientToken:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'Short-lived, per-request JWT (`ES256`) minted at request creation, scoped

        `{tenant, requestId, purpose, method, allowedOrigins}`. Safe to hand to a browser/mobile client:

        it cannot create requests, read tenant data, or touch other requests. For browser clients the API

        enforces `Origin` against `allowedOrigins` (rejects cross-origin replay).

        '
    downloadToken:
      type: apiKey
      in: query
      name: downloadToken
      description: One-off token returned with a completed sign result, for fetching the signed document.
externalDocs:
  description: Quickstart, SDKs, test data, pricing and lifecycle policy
  url: https://atk.tvarka.pro/docs/
x-publication:
  specialistContracts:
  - https://atk.tvarka.pro/openapi/auth.yaml
  - https://atk.tvarka.pro/openapi/sign.yaml
  postmanCollections:
  - https://atk.tvarka.pro/postman/auth.json
  - https://atk.tvarka.pro/postman/sign.json