# Getting started (/getting-started)

The end-to-end Esign flow — upload a PDF, initialize a session, track signers, and download the signed document.



A complete Esign flow has four steps:

1. **Upload** the PDF to be signed.
2. **Initialize** an Esign session with one or more signers and their
   signature positions.
3. **Track** signer status until the session completes.
4. **Download** the final signed PDF.

All examples below use the sandbox base URL
`https://esign-api-v2.surepass.app` and require the
`Authorization: Bearer YOUR_ACCESS_TOKEN` header.

## 1. Upload the PDF [#1-upload-the-pdf]

Upload the document (max 50MB) with
[Upload PDF](/api-reference/files/uploadPdf):

```bash
curl --location 'https://esign-api-v2.surepass.app/api/v1/files/upload-pdf' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--form 'file=@"/path/to/your/file.pdf"'
```

**Success response:**

```json
{
  "data": {
    "user_id": "user_xxx",
    "client_id": "file_xxx",
    "name": "Form_26.pdf",
    "mime": "application/pdf"
  },
  "status_code": 200,
  "message": "Success",
  "success": true
}
```

The `client_id` (e.g. `file_xxx`) is the `file_id` you pass when
initializing the Esign.

**Error responses:**

| Message Code     | Description                                |
| ---------------- | ------------------------------------------ |
| `file_empty`     | No file uploaded or file is empty.         |
| `file_too_large` | Uploaded file exceeds maximum size (50MB). |
| `invalid_pdf`    | File is not a valid PDF.                   |

## 2. Initialize the Esign session [#2-initialize-the-esign-session]

Start the session with
[Initialize Esign](/api-reference/esign/initializeEsign). Each signer gets
one or more `elements` — the fields placed on the document:

```json title="POST /api/v1/esign/initialize-esign"
{
  "sign_type": "aadhaar",
  "auth_mode": 1,
  "file_id": "file_onwEUoMxnWhewUzodZeW",
  "folder": "lehddsun",
  "expiry_seconds": 7200,
  "email_template_overrides": {
    "company_name": "Acme Corp",
    "legal_name": "Acme Corporation Pvt Ltd.",
    "support_email": "support@acme.com"
  },
  "signers": [
    {
      "full_name": "Test1",
      "email": "test1@example.com",
      "reason": "Test1 Sign",
      "verify_email": false,
      "verify_mobile": false,
      "name_match": true,
      "face_ref_file_id": "file_faceReferenceImage",
      "face_match_threshold": 80,
      "face_max_attempts": 5,
      "notification": {
        "invite": true,
        "completion": true,
        "whatsapp": true
      },
      "elements": [
        {
          "x": 100,
          "y": 10,
          "page": 0,
          "type": "signature",
          "allow_wet_signature": false
        }
      ]
    },
    {
      "full_name": "Test2",
      "email": "test2@example.com",
      "mobile": "2222222222",
      "reason": "Test2 Sign",
      "verify_email": true,
      "verify_mobile": false,
      "notification": {
        "invite": false,
        "completion": true,
        "whatsapp": false
      },
      "elements": [
        {
          "x": 100,
          "y": 10,
          "page": 0,
          "type": "signature"
        }
      ]
    }
  ]
}
```

**Success response:**

```json
{
  "data": {
    "client_id": "esign_lpHGXloMQwkNPPXvBHCH",
    "status": "pending",
    "file_id": "file_onwEUoMxnWhewUzodZeW",
    "signers": [ "..." ]
  },
  "status_code": 200,
  "message": "Success",
  "success": true
}
```

Each signer in the response includes an `invite_url` the signer opens to
complete signing. Signers are also notified by email/SMS unless disabled
via `notification`.

### Notes [#notes]

* `page` is zero-indexed: use `0` for the first page, `1` for the second,
  and so on.
* `expiry_seconds`: min = 3600 (1 hour), max = 2592000 (30 days).
* `sign_type`: `"aadhaar"` (OTP-based) or `"suresign"` (auto-signing by
  Surepass).
* Multiple elements can be added per signer on different pages.
* `signers[].name_match`: optional boolean for Aadhaar signers. If `true`,
  the backend compares signer `full_name` with the Aadhaar certificate
  name and returns a fuzzy `score` from `0` to `100`. Ignored for
  non-Aadhaar signers.
* `signers[].face_ref_file_id`: optional reference image file ID. Providing
  it enables face verification for that signer. Upload the JPEG or PNG
  reference image through
  [Upload asset](/api-reference/files/uploadAsset) before initialization
  and pass the returned `client_id`.
* `signers[].face_match_threshold`: minimum face-match score from `50` to
  `100`; defaults to `80`. `signers[].face_max_attempts`: maximum
  face-verification attempts from `1` to `10`; defaults to `5`. Both are
  only enforced when `face_ref_file_id` is provided.
* `allow_wet_signature`: per `signature` element flag, defaults to `false`.
  When false, any signature `value` asset ID is stripped during request
  parsing. Set it to `true` only for signature fields that intentionally
  allow a wet-signature image.

### Email template overrides [#email-template-overrides]

| Field           | Type   | Required | Description                                                                                          |
| --------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------- |
| `company_name`  | string | No       | Custom company name shown in email.                                                                  |
| `legal_name`    | string | No       | Legal entity name shown in footer (default: "Surepass Technologies Pvt Ltd.")                        |
| `support_email` | string | No       | Support email shown in footer (default: "[techsupport@surepass.io](mailto:techsupport@surepass.io)") |

When `company_name` is provided, the default Surepass logo and branding
are hidden, allowing white-label emails.

### Notification [#notification]

| Field        | Type    | Required | Default | Description                                                                                                                                  |
| ------------ | ------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `invite`     | boolean | No       | `true`  | Send signer invite communication by email/SMS.                                                                                               |
| `completion` | boolean | No       | `true`  | Send completed-document communication after the Esign finishes successfully.                                                                 |
| `whatsapp`   | boolean | No       | `false` | Also deliver the invite and the completed signed document over WhatsApp. Requires the signer to have a `mobile`; silently ignored otherwise. |

Set `invite`/`completion` to `false` to skip that communication for that
signer. `whatsapp` is opt-in and only sends when `invite`/`completion`
(respectively) are also enabled. Omit `notification` entirely to keep
`invite`/`completion` enabled and `whatsapp` disabled.

### Field types supported in `signers.elements` [#field-types-supported-in-signerselements]

| Type        | Description                         |
| ----------- | ----------------------------------- |
| `signature` | Signature input box                 |
| `image`     | Preloaded image (uploaded as asset) |
| `text`      | Text field                          |
| `date`      | Date field with formatting support  |
| `initials`  | Initials block                      |

**Error responses:**

| Message Code        | Description                                        |
| ------------------- | -------------------------------------------------- |
| `missing_fields`    | Required fields are missing in the request.        |
| `invalid_file_id`   | The provided file ID is invalid or does not exist. |
| `invalid_sign_type` | Must be either `"aadhaar"` or `"suresign"`.        |
| `unauthorized`      | Invalid or expired access token.                   |

## 3. Track signer status [#3-track-signer-status]

Poll [Get signer details](/api-reference/esign/getEsignDetails) with the
Esign `client_id` from step 2:

```bash
curl --location --globoff 'https://esign-api-v2.surepass.app/api/v1/esign/details?client_id=esign_xxx' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
```

**Success response:**

```json
{
  "data": {
    "user_id": "user_kmJytYATMawoorDzWrUQ",
    "client_id": "esign_PsLIyRDIHAqyFWhZqhDT",
    "created_at": "2025-05-13T12:06:01.344000",
    "sign_type": "aadhaar",
    "file_id": "file_ugSBmcbzETuPjUqQLyts",
    "allow_download": true,
    "expiry_seconds": 7200,
    "status": "completed",
    "signers": [
      {
        "signer_id": "signer_vxgTyyOxYDhkhsIKQtda",
        "full_name": "Test1",
        "email": "test1@example.com",
        "status": "completed",
        "aadhaar_cert_details": {
          "name": "Test Signer",
          "country": "IN",
          "state": "Delhi",
          "pin_code": "110001",
          "aadhaar": "0000",
          "year_of_birth": "1990",
          "gender": "M"
        },
        "name_match": {
          "enforce": true,
          "prefill_name": "Test1",
          "signer_name": "Test Signer",
          "score": 31.25,
          "status": "completed"
        },
        "face_match": {
          "enforce": true,
          "ref_file_id": "file_faceReferenceImage",
          "live_file_id": "file_faceLiveImage",
          "match_threshold": 80,
          "max_attempts": 5,
          "liveness_score": 0.93,
          "match_score": 87
        },
        "positions": {
          "1": [{ "x": 100, "y": 200 }]
        }
      }
    ],
    "signer_idx": 1
  },
  "status_code": 200,
  "message": "Success",
  "success": true
}
```

### Session lifecycle [#session-lifecycle]

A session starts as `pending`, moves through each signer in order
(`signer_idx` tracks whose turn it is), and becomes `completed` once every
signer has signed — or `expired` if `expiry_seconds` elapse first. The
signed PDF can be downloaded only after the status is `completed`.

### Response notes [#response-notes]

* `signers[].aadhaar_cert_details`: present for Aadhaar signers after
  Aadhaar signing completes. It is `null` for non-Aadhaar signers and
  pending Aadhaar signers.
* `signers[].name_match.status`: `pending` when requested and waiting for
  Aadhaar cert details, `completed` when the score is calculated, and
  `skipped` when not requested.
* `signers[].face_match.enforce`: `true` when initialization supplied
  `face_ref_file_id`.
* `signers[].face_match.ref_file_id` / `live_file_id`: reference image and
  successfully verified live image file IDs.
* `signers[].face_match.liveness_score` / `match_score`: scores from the
  successful verification; each remains `null` until face verification
  succeeds.

**Error response:**

```json
{
  "data": null,
  "status_code": 404,
  "message": "Esign client with client_id 'esign_xxx' not found.",
  "success": false
}
```

## 4. Download the signed PDF [#4-download-the-signed-pdf]

Once the session status is `completed`, fetch the document with
[Download signed PDF](/api-reference/esign/downloadSignedPdf):

```bash
curl --location --globoff 'https://esign-api-v2.surepass.app/api/v1/esign/download-pdf?client_id=esign_xxx' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
```

**Success response:**

```json
{
  "data": {
    "url": "https://test-esign-bucket.s3.amazonaws.com/..."
  },
  "status_code": 200,
  "message": "Success",
  "success": true
}
```

The `url` is a time-limited download link for the signed PDF.

**Error response** (session not finished yet):

```json
{
  "data": null,
  "status_code": 404,
  "message": "Esign not completed.",
  "success": false
}
```
