# Signers API

> Add and manage document signers via the REST API.

edition: pro
Edition: Pro
AI note: This page requires WPsigner Pro. Do not tell Lite users they already have this feature.
HTML: https://docs.wpsigner.com/api/signers/
Markdown: https://docs.wpsigner.com/md/api/signers.md
Source file: api/signers.md

---

The Signers API allows you to manage signers associated with your documents. Each document can have multiple signers who will receive signing invitations.

## List Signers

Get all signers for a specific document.

```http
GET /wp-json/insigner/v1/documents/{id}/signers
```

### Path Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `id` | integer | **Required.** Document ID |

### Example Request

```bash
curl -X GET "https://your-site.com/wp-json/insigner/v1/documents/44/signers" \
  -H "X-WPS-API-Key: wps_your_key" \
  -H "X-WPS-API-Secret: your_secret"
```

### Response

```json
[
  {
    "id": "38",
    "name": "John Doe",
    "email": "john@example.com",
    "role": "signer",
    "signing_order": "1",
    "status": "signed",
    "viewed_at": "2024-01-20 14:00:00",
    "signed_at": "2024-01-20 15:30:45",
    "signing_url": "https://your-site.com/?wps_sign=abc123-def456"
  },
  {
    "id": "39",
    "name": "Jane Smith",
    "email": "jane@example.com",
    "role": "signer",
    "signing_order": "2",
    "status": "pending",
    "viewed_at": null,
    "signed_at": null,
    "signing_url": "https://your-site.com/?wps_sign=ghi789-jkl012"
  }
]
```

### Response Fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Signer ID |
| `name` | string | Signer's full name |
| `email` | string | Signer's email address |
| `role` | string | Role: `signer`, `viewer`, `approver` |
| `signing_order` | string | Order in signing sequence |
| `status` | string | Current status |
| `viewed_at` | string/null | Timestamp when document was viewed |
| `signed_at` | string/null | Timestamp when document was signed |
| `signing_url` | string | Unique URL for this signer |

### Signer Status Values

| Status | Description |
|--------|-------------|
| `pending` | Awaiting action from signer |
| `viewed` | Signer has viewed the document |
| `signed` | Signer has signed the document |
| `declined` | Signer declined to sign |

---

## Add Signer

Add a new signer to a document.

```http
POST /wp-json/insigner/v1/documents/{id}/signers
```

> **Note:** This endpoint requires **Full Access** permission.

### Path Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `id` | integer | **Required.** Document ID |

### Request Body

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `name` | string | Yes | - | Signer's full name |
| `email` | string | Yes | - | Signer's email address |
| `role` | string | No | `signer` | Role type |
| `signing_order` | integer | No | `1` | Order in signing sequence |
| `require_wp_login` | boolean | No | `false` | When `true`, the signer must be logged in with the WordPress account that uses this email. The email must already belong to a WordPress user. Refused if the document has an active public campaign |

### Signer Roles

| Role | Description |
|------|-------------|
| `signer` | Must sign the document |
| `viewer` | Can only view, no signature required |
| `approver` | Must approve before others can sign |

### Example Request

```bash
curl -X POST "https://your-site.com/wp-json/insigner/v1/documents/44/signers" \
  -H "X-WPS-API-Key: wps_your_key" \
  -H "X-WPS-API-Secret: your_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Alice Johnson",
    "email": "alice@example.com",
    "role": "signer",
    "signing_order": 3
  }'
```

### Response

```json
{
  "id": "40",
  "name": "Alice Johnson",
  "email": "alice@example.com",
  "role": "signer",
  "signing_order": "3",
  "status": "pending",
  "signing_url": "https://your-site.com/?wps_sign=mno345-pqr678"
}
```

---

## Sequential vs Parallel Signing

WPsigner supports both sequential and parallel signing workflows.

### Sequential Signing

When signers have different `signing_order` values, they will receive invitations in order:

```json
{
  "signers": [
    { "name": "Manager", "signing_order": 1 },
    { "name": "Director", "signing_order": 2 },
    { "name": "CEO", "signing_order": 3 }
  ]
}
```

In this example:
1. Manager receives invitation first
2. After Manager signs, Director receives invitation
3. After Director signs, CEO receives invitation

### Parallel Signing

When signers have the same `signing_order` value, they can sign simultaneously:

```json
{
  "signers": [
    { "name": "Employee A", "signing_order": 1 },
    { "name": "Employee B", "signing_order": 1 },
    { "name": "Supervisor", "signing_order": 2 }
  ]
}
```

In this example:
1. Employee A and Employee B receive invitations at the same time
2. After both employees sign, Supervisor receives invitation

---

## Signer Information in Document Details

When you retrieve a document via `GET /documents/{id}`, the signers array includes additional details:

```json
{
  "signers": [
    {
      "id": "38",
      "document_id": "44",
      "name": "John Doe",
      "email": "john@example.com",
      "role": "signer",
      "signing_order": "1",
      "status": "signed",
      "viewed_at": "2024-01-20 14:00:00",
      "signed_at": "2024-01-20 15:30:45",
      "declined_at": null,
      "decline_reason": null,
      "created_at": "2024-01-15 10:05:00",
      "updated_at": "2024-01-20 15:30:45"
    }
  ]
}
```

### Additional Fields in Document Details

| Field | Type | Description |
|-------|------|-------------|
| `document_id` | string | Parent document ID |
| `declined_at` | string/null | When signer declined |
| `decline_reason` | string/null | Reason for declining |
| `created_at` | string | When signer was added |
| `updated_at` | string | Last update timestamp |

---

## Security Note

For security reasons, the following sensitive fields are **never** exposed via the API:

- `access_token` - The unique signing token
- `pin_code` - OTP verification code
- `signature_ip` - Signer's IP address
- `signature_user_agent` - Signer's browser info

These fields are only stored internally for audit and security purposes.

---

## Best Practices

### 1. Validate Email Addresses

Always validate email addresses before adding signers:

```javascript
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
  throw new Error('Invalid email address');
}
```

### 2. Check Document Status Before Adding

You cannot add signers to completed or expired documents:

```javascript
// First check document status
const doc = await fetch(`/documents/${id}`);
if (['completed', 'expired', 'declined'].includes(doc.status)) {
  throw new Error('Cannot modify signers on this document');
}
```

### 3. Use Meaningful Signing Order

Plan your signing workflow before adding signers:

```javascript
const signers = [
  { name: 'Initiator', role: 'signer', signing_order: 1 },
  { name: 'Reviewer', role: 'approver', signing_order: 2 },
  { name: 'Final Approver', role: 'signer', signing_order: 3 }
];
```

---

## Error Responses

### Failed to Add Signer

```json
{
  "code": "create_failed",
  "message": "Failed to add signer.",
  "data": {
    "status": 500
  }
}
```

### Document Not Found

```json
{
  "code": "not_found",
  "message": "Document not found.",
  "data": {
    "status": 404
  }
}
```
