> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vumasign.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pre-signed salary letters

> Send a batch of salary adjustment letters that go out already signed for the employer, under a standing authorisation, and try it with a test key first.

export const testKeyPrefix = "vsk_test_";

export const scopeAuthorisationsInvite = "authorisations:invite";

export const scopeAuthorisationsApply = "authorisations:apply";

export const salaryLetterValueKey = "new_salary";

export const salaryLetterRole = "Employer";

export const saWithoutSignerCode = "authorisation_without_signer";

export const saStatusActive = "active";

export const saNotEnabledCode = "standing_authorisations_not_enabled";

export const saMaxValidityMonths = "12";

export const saExpiresDuringBatchCode = "authorisation_expires_during_batch";

export const saBatchWindow = "1 hour";

export const liveKeyPrefix = "vsk_live_";

export const eventAuthorisationGranted = "authorisation.granted";

This guide sends salary adjustment letters in bulk. Each letter is signed for the employer by an HR
director under a [standing authorisation](/concepts/standing-authorisations), and goes out to the
employee to accept. The employee is the only person emailed.

Do it end to end with a <code>{testKeyPrefix}</code> key first. Nothing a test key makes binds anybody,
and the mandate and the letters are watermarked.

## Before you start

* **Standing authorisations are switched on** for your organisation by Vumasign, separately for sandbox
  and live. Until then every request answers <code>{saNotEnabledCode}</code>.
* **A key that names both scopes**: <code>{scopeAuthorisationsInvite}</code> to request the
  authorisation and <code>{scopeAuthorisationsApply}</code> to apply it. A full-access key holds
  neither. An owner or admin adds them under **Settings → API keys**.
* **A brand** for the letters. The authorisation covers only documents sent under that brand.

## 1. Mark the letter

Use the ordinary [text tags](/concepts/text-tags). Nothing in the letter says "pre-signed": the
choice is made when you send.

```text theme={null}
Your new monthly salary is <<text:Employer:key(new_salary)>>.
Yours sincerely,
<<sig:Employer>>
<<name:Employer>>, <<title:Employer>>
<<company:Employer>>        <<datesigned:Employer>>
Accepted: <<sig:Employee>>    <<datesigned:Employee>>
```

Make it a template with the roles `Employee` and <code>{salaryLetterRole}</code>. On the
pre-signed role, Vumasign fills the signature, the grantor's name, the title they signed the mandate
with, the legal entity and the date. The figure is yours: send it as a locked value for the key
<code>{salaryLetterValueKey}</code>. Don't put an `email` tag on the pre-signed role; it is refused.

## 2. Request the authorisation, under a test key

Ask the HR director to sign the mandate. Under a test key the grantor must be a verified test recipient
or a member of your organisation, so use your own address for the trial:

```bash theme={null}
curl https://app.vumasign.com/api/v1/standing-authorisations/invitations \
  -H "Authorization: Bearer $VUMASIGN_TEST_KEY" \
  -H "Idempotency-Key: salary-letters-trial" \
  -H "Content-Type: application/json" \
  -d '{ "brand_id": "<your brand id>",
        "legal_entity": { "name": "NTT DATA South Africa (Pty) Ltd" },
        "grantor": { "name": "Naledi Mokoena", "email": "<a verified address>", "job_title": "HR Director" },
        "intended_use": "Salary adjustment letters",
        "valid_until": "<the end date>" }'
```

`valid_until` may be at most {saMaxValidityMonths} months away. Keep the `id` the answer returns.

The grantor receives the mandate, enters the code emailed to them, and signs it. When the signed
mandate is sealed you receive <code>{eventAuthorisationGranted}</code>, and the authorisation reads
<code>{saStatusActive}</code>.

## 3. Send a batch, under the same test key

Each row names the employee as a signer and the authorisation on the employer's role, with the figure
locked:

```json theme={null}
{ "template_id": "<the letter template>",
  "brand_id": "<your brand id>",
  "send": true,
  "rows": [
    { "recipients": [
        { "role": "Employee", "name": "Thabo Nkosi", "email": "<a verified address>" },
        { "role": "Employer",
          "completion": { "type": "standing_authorisation", "authorisation_id": "<the id>" } } ],
      "values": [ { "subject": null, "key": "new_salary", "value": "R 41 500", "locked": true } ] } ] }
```

Post it to `POST /api/v1/envelopes/batches`. Each letter goes out already signed by the employer.
In each envelope the employer's recipient has `completion_basis: "standing_authorisation"`, and the
grantor receives no email about any letter.

The employee must be a signing recipient. A letter with nobody else to sign or approve is refused
<code>{saWithoutSignerCode}</code>.

## 4. Go live

Repeat steps 2 and 3 with a <code>{liveKeyPrefix}</code> key and the real grantor. A sandbox
authorisation never pre-signs a live letter, and a live one never pre-signs a sandbox letter.

## How a batch behaves

* **Refused up front, or not at all.** If the authorisation ends within {saBatchWindow} of the request,
  the whole batch is refused <code>{saExpiresDuringBatchCode}</code> before any letter is created or
  sent. Use an authorisation with more time left.
* **A revoke part-way through** stops the rows after it that name the same authorisation. They are not
  sent, each says why, and each stays a draft. Letters already sent stay signed: the authorisation was
  in force when each was applied.
* **Each row is its own answer.** A row refused for its own data does not stop the others.

## In the dashboard

An owner or admin can do the same from **Send in bulk**: choose "Pre-sign as …" for the employer's
role, choose the file, and confirm the sentence that names the grantor, the role, the authorisation
and how many letters. The bulk screen sends under your default brand.

## Related

[Standing authorisations](/concepts/standing-authorisations) · [Text tags](/concepts/text-tags) ·
[Test keys and live keys](/concepts/test-and-live) · [Webhooks](/guides/webhooks)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.