# Create a templated document for a member

`POST /api/members/{memberId}/documents/populate-template`

- **Success:** `200 OK`
- **Products:** Operator (`FOH`)
- **Features:** Front of House Generic Access (`FOHGENERIC`)

HTML version: [Create a templated document for a member](https://support.gladstonesoftware.cloud/reference/members/create-a-templated-document-for-a-member)

## Overview

Builds a PDF for a member from a template that Gladstone already holds, by stamping your values
into the template's form fields. You send no file: the template configured for the site you name is
filled in with the placeholders you supply and flattened so the result is no longer editable, the
finished PDF is stored against the member, and you get `200 OK` whose body is a single JSON string
containing a read-only link to it.

Reach for this endpoint when the document's wording is fixed and only the values change — the
opposite case to [Create a document for a member](create-a-document-for-a-member.md),
which takes a finished file from you as multipart form data and stamps nothing. If you already
have the PDF, use that one; if you want Gladstone to produce it, use this one.

Only one template is implemented: the **direct debit mandate**, the paper instruction a member
signs to authorise collections from their bank account. That is `templateType` `0`, and any other
value fails. There is a second route to the same template,
[Generate direct debit mandate document](generate-direct-debit-mandate-document.md),
and the difference matters. That route marks the mandate as *confirmed*, makes the document visible
to the member, and refuses to run if the member already holds a confirmed mandate. This route does
none of those things: the mandate it produces is unconfirmed, and because the document list hides
unconfirmed mandates and hides everything not marked member-visible, a member listing their own
documents will not see what you generated here. Use this route to produce a mandate for signature;
use the other one when the mandate is being taken as part of a purchase.

Before the PDF is built, the endpoint checks that the member exists, the memberships you named belong to
that member, the site exists, a document type is configured for the template, and every expected
placeholder is present. Site configuration does a lot of work here: the template file, the
logo, the bank instruction text and the direct debit guarantee text are all configuration values
resolved for `siteId`, so the same request can succeed at one site and fail with `422` at another
that has not been set up.

Access is checked first. When your token carries a member id it must equal
`{memberId}`, or you get `403` and `The given member ID of {memberId} does not belong to the logged
in member`; linked members are **not** accepted on this route. Tokens with no member id in them
(staff and integration tokens) are not subject to that check.

The link you get back is short-lived — signed for a 20-minute window with 20 minutes of clock-skew
allowance — so do not store it. Fetch a fresh one with
[Retrieve a document associated with a member](retrieve-a-document-associated-with-a-member.md).

## Endpoint

`POST {base_url}/api/members/{memberId}/documents/populate-template`

`{base_url}` is the environment URL issued to your integration. See [Authenticating with Gladstone APIs](../../guides/authenticating-with-gladstone-apis.md).

## Path parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `memberId` | integer (int32) | Yes | The member the generated document is filed against, and the member whose memberships `membershipIds` are checked against. The member must exist, or the call fails with `404` and `The member with the ID {memberId} doesn't exist`. When your token carries a member id, this value must equal it — linked members are not accepted on this route. |

## Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `siteId` | string | Yes | The site whose configuration supplies the template — the template file, and for the direct debit mandate also the logo, the bank instruction text and the guarantee text. Take it from `id` in [Get all sites with optional filtering](../configuration/get-all-sites-with-optional-filtering.md). It is matched case-insensitively, but the site must exist or the call fails with `404` and `The given site ID {siteId} doesn't exist`. Required; a request without it is rejected with `400`. |
| `membershipIds` | array of integer | No | The member's memberships to associate the generated document with, which is how a mandate is tied to the subscriptions it pays for. Every id must exist **and** belong to the member in the path, or the whole request fails with `400` and `One or more membership IDs do not exist or are not associated with member ID {memberId}.` Omit it, or send an empty array, to store the document against the member without linking it to any membership. |
| `requestPlaceholderNamesAndValues` | object | Yes | A flat map of placeholder name to the text stamped into that field of the template. Keys are matched case-insensitively against the names the template expects, and the values are written into the PDF's form fields as-is. For `templateType` `0` all ten of `AccountName`, `AccountNumber`, `SortCode`, `ServiceUserNumber`, `Reference`, `Date`, `Signature`, `BankAddress`, `BranchName` and `PostalCode` must be present; the first seven must also carry a non-null value, while `BankAddress`, `BranchName` and `PostalCode` may be present with a null value and are then stamped as blank. A key that is absent, or one of the first seven sent as null, fails with `400` and `The placeholder {name} was missing from the request or the provided value was null or empty`. `BankAddress` is treated specially: it is split on commas into the mandate's three branch-address lines, and only the first three comma-separated parts are used. |
| `templateType` | integer (enum) | No | Which stored template to fill. `0` is the direct debit mandate and is the only template implemented; it is also what you get when you omit the field, since `0` is the default. The name `DDMandate` is accepted in place of the number. Any other value returns `500`. The value also decides which placeholder keys are required and which document type the result is filed under. |

## Sample request

```bash title="cURL"
curl -X POST '{base_url}/api/members/{memberId}/documents/populate-template' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "siteId": "string",
  "membershipIds": [
    12345
  ],
  "requestPlaceholderNamesAndValues": "string",
  "templateType": 0
}'
```

## Sample response

```json title="200 OK"
"string"
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | A required placeholder was missing or null — `The placeholder {name} was missing from the request or the provided value was null or empty`; or one of `membershipIds` does not exist or is not the member's — `One or more membership IDs do not exist or are not associated with member ID {memberId}.` A request with no `siteId` is also rejected here. |
| `404` | Not found | No member has the id in the path — `The member with the ID {memberId} doesn't exist` — or `siteId` matches no site — `The given site ID {siteId} doesn't exist`. |
| `422` | Unprocessable entity | The tenant or site is not configured for this template, so the request is valid but cannot be carried out. Either no document type is set up for the template — `No document type is setup associated with the key DDMandate`; or a required configuration value is missing — `No configuration is setup associated with any of the keys {keys}` or `The configurations with the keys: {keys} are null or empty but nulls are not allowed and no overrides are present`, covering the template file location, the bank instruction and the guarantee text; or the template file itself could not be loaded — `The template failed to load from the storage`. None of these are fixable from the client side. |
| `500` | Internal server error | An unexpected server-side failure — most commonly a `templateType` other than the direct debit mandate, which is not supported and is not reported as a validation error. Also covers failures filling in or storing the PDF; the document record is created before the file is stored, so a failure there can leave a document record with no file behind it. |
