# PAdES signing

> **This information is outdated**
>
> This information is **outdated** and will be removed. See the new BankID Signing documentation [here](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/signdoc-intro.md)

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. Request an access token with the `signdoc/read_write` scope using [Client Credentials](https://docs.stoe.no/bankid-oidc-provider/flows.md) flow.
2. Create a sign order by uploading the document(s) to be signed to the SignDoc API. You will receive a `sign_id`.
3. Redirect the end user to the BankID authorize endpoint with the `sign` scope and the `sign_id` parameter.
4. The end user signs the document(s).
5. You can check the status of the signing process using the SignDoc API. (Optional)
6. BankID returns to your callback URL following the standard [Authorization Code](https://docs.stoe.no/bankid-oidc-provider/flows.md) flow.
7. Your service exchanges the `code` for tokens and [verifies](https://docs.stoe.no/bankid-oidc-provider/advanced-topics/verify-token.md) them.
8. Download the signed document(s) using the SignDoc API once the signing process is complete.

> **Warning**
>
> The sign order is only valid for 90 seconds **before** signing starts, and 90 seconds **after** signing ends.

## Sequence diagram

```mermaid
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

> **Note**
>
> You will always find the up-to-date URL for the SignDoc API in the [OpenID Configuration](https://docs.stoe.no/bankid-oidc-provider/api/openid-configuration.md)
>
> - as `signdoc-baseurl`.

API reference: [OpenAPI specification](https://docs.stoe.no/bankid-oidc-provider/api/signing/signdoc-pades.yaml)

## 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](https://docs.stoe.no/bankid-oidc-provider/api/openid-configuration.md).

##### Headers

```
Authorization: Bearer [access_token]
Content-Type: application/json
```

##### Body

```json
{
  "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:

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

With `pdfSpec` specified:

```json
{
  "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.

```json
{
    "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

```json
{
  "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"
}
```
