Skip to main content
Developer

PAdES signing#

View as Markdown
On this page

BankID offers a PAdES (PDF Advanced Electronic Signatures) signing solution that allows you to sign PDF documents for long-term validation.

  • Supports multiple end user signatures through serial signing where the output from one signing session is used as input for the next
  • Allows you to configure the visible seal applied to the PDF document after signing.
  • Supports end-user signature stand-alone (as well as end-user and merchant signatures)

Flow#

The BankID PAdES signing flow makes use of the SignDoc API to:

  • create a sign order by uploading the document(s) to be signed
  • check the status of the signing process
  • download the signed document(s) after the signing process is complete

In order to use the PAdES signing flow, you need to get an access token with the signdoc/read_write scope and use it to create a sign order.

Furthermore, you need to redirect the end user to the BankID authorize endpoint with the sign scope and the sign_id parameter.

Finally, you can download the signed document(s) using the SignDoc API once the signing process is complete.

Steps#

  1. 1

    Request an access token with the signdoc/read_write scope using Client Credentials flow.

  2. 2

    Create a sign order by uploading the document(s) to be signed to the SignDoc API. You will receive a sign_id.

  3. 3

    Redirect the end user to the BankID authorize endpoint with the sign scope and the sign_id parameter.

  4. 4

    The end user signs the document(s).

  5. 5

    You can check the status of the signing process using the SignDoc API. (Optional)

  6. 6

    BankID returns to your callback URL following the standard Authorization Code flow.

  7. 7

    Your service exchanges the code for tokens and verifies them.

  8. 8

    Download the signed document(s) using the SignDoc API once the signing process is complete.

Sequence diagram#

sequenceDiagram
    actor u as User
    participant Merchant as Your Web App
    participant BankID as BankID
    participant SignDoc as SignDoc API
    u ->> Merchant: Request signing
    Note right of Merchant: (1) Client requests access token
    Merchant->>BankID: POST /token with `signdoc/read_write` scope
    BankID-->>Merchant: Access token
    Note right of Merchant: (2) Client creates sign order
    Merchant-->>SignDoc: POST /signdoc/pades with parameters and document(s) data
    SignDoc-->>Merchant: Sign ID
    Note right of Merchant: (3) Client redirects user to BankID with sign_id
    Merchant->>BankID: GET /authorize?scope=sign&sign_id=xxxx-xxxx&client_id=...
    BankID-->> Merchant: Redirect to callback with code
    Note right of Merchant: (7) Client fetches tokens and verifies
    Merchant->>BankID: POST /token with code
    BankID-->>Merchant: ID tokens
    Note right of Merchant: (8) Client downloads signed document(s)
    Merchant->>SignDoc: DELETE /signdoc/pades?sign_id={sign_id}
    SignDoc-->>Merchant: Signing results and document(s)
    Merchant->>u: Signing complete

API#

Examples#

Create a sign order#

Request#

POST [signdoc-baseurl]/signdoc/pades

You can find the signdoc-baseurl for the appropriate environment in the OpenID Configuration.

Headers#
Authorization: Bearer [access_token]
Content-Type: application/json
Body#
{
  "signProperties": {
    "orderName": "My order name",
    "documentDisplayMode": "interior",
    "showConfirmation": true,
    "showUnderstanding": true,
    "timeoutSeconds": 1800
  },
  "padesSignProperties": {
    "addVisualSeals": true
  },
  "documents": [
    {
      "description": "My document",
      "pdf": "JVBER...",
      "pdfSpec": "PDFA_2B",
      "merchantSealPos": {
        "x": 100,
        "y": 80,
        "page": 1
      },
      "endUserSealPos": {
        "x": 200,
        "y": 80,
        "page": 1
      }
    }
  ],
  "resultContent": [
    "padesSignedPdf",
    "padesAppendix",
    "documentHash"
  ]
}

Response#

Status#
201 Created
Headers#
Content-Type: application/json
Body#

The result contains the sign_id reference which is used to identify the sign order.

With no pdfSpec specified:

{
  "signId": "2a8d69ba-2607-9a1e-9e60-bdb6cc67eacf"
}

With pdfSpec specified:

{
  "sign_id": "2a8d69ba-2607-9a1e-9e60-bdb6cc67eacf",
  "conversionResults": [
    {
      "conversionId": "d886b218-af9f-4765-a9e1-d819fec6abbe",
      "description": "My order name - 1",
      "converted": true,
      "conversionErrors": [],
      "conversionWarnings": [
        "Visual differences in output PDF",
        "Removed interactive elements such as actions or annotations"
      ]
    },
    {
      "conversionId": "1b4c673a-9d9e-4680-8aa2-810a31d50d8c",
      "description": "My order name - 2",
      "converted": true,
      "conversionErrors": [],
      "conversionWarnings": [
        "Visual differences in output PDF",
        "Removed interactive elements such as actions or annotations"
      ]
    }
  ]
}
Conversion results#

conversionWarnings contains an array of warnings that occurred during the conversion.

Possible values are:

VISUAL_DIFF("Visual differences in output PDF")
COLORANTS("Resolve name collisions of colorants")
OCG_REMOVED("Removed optional content groups (layers)")
TRANSP_REMOVED("Transparency removed")
XMP_REMOVED("Removed non convertible XMP metadata")
FONT_SUBST("Font substituted")
ACTION_REMOVED( "Removed interactive elements such as actions or annotations")
STRUCTURE_REMOVED("Structure removed")

Documents that could not be converted will have a list of errors in conversionErrors:

CORRUPT("Document is corrupt")
DOC_SIGNED("Document contains signatures")
EF_REMOVED("Embedded files removed")
GENERIC_ERROR("Unknown error")
DISABLED("PDF conversion is disabled")

In CURRENT the response will always be DISABLED("PDF conversion is disabled") and "converted" = false

Check the status of a sign order#

Request#

GET [signdoc-baseurl]/signdoc/pades?sign_id={sign_id}
Headers#
Authorization: Bearer [access_token]
Content-Type: application/json

Response#

Status#
200 OK
Body#

Sign order was found. Returns the order state.

{
    "orderState": "ORDER_RECEIVED"
}

Possible values are:

  • ORDER_RECEIVED
  • GRABBED_BY_IDP
  • GENERATING_MERCHANT_SEALS
  • USER_SIGNING
  • ADD_DOCUMENT_SECURITY_STORE
  • FAILED
  • CANCELLED
  • SIGN_COMPLETED

Download signing results#

Request#

DELETE [signdoc-baseurl]/signdoc/pades?sign_id={sign_id}
Headers#
Authorization: Bearer [access_token]
Content-Type: application/json

Response#

Status#
200 OK
Body#
{
  "signingResults": [
    {
      "signedDocumentSha256": "u0XXG...",
      "padesSignedPdf": "JVBER...",
      "padesAppendix": "DQoxMiAw...",
      "description": "My order name - 1",
      "unsignedDocumentSha256": "QJ2y8..."
    }
  ],
  "signId": "4120de56-4391-4e5a-adea-a28e62daac7e",
  "orderName": "My order name",
  "orderState": "SIGN_COMPLETED"
}

Was this page helpful?