Generate direct debit mandate document

POST /api/members/{memberId}/documents/pre-purchase-dd-mandate

Success: 201 Created

Overview

Produces the Direct Debit Instruction PDF a member signs when they buy a membership paid by direct debit, and returns the URL of the generated file. The document is unconfirmed: it records the mandate the member is agreeing to, before any invoice has been paid. A second, confirmed mandate is generated automatically by the platform once the membership invoice is paid — you do not call anything for that.

Call this immediately after Create members with memberships, which is where the entire request body comes from. That call returns a signed payload; you send it back here unaltered. The payload is signed with an HMAC that Gladstone verifies, so you cannot hand-build this request, edit a value in it, or reuse a payload from a different purchase — any of those fail with 400 and The request is invalid.

The call is also time-limited: the timeStamp inside the signed payload is checked, and a payload whose timestamp is more than ten minutes in the future is rejected.

To build the mandate, the platform pulls together the tenant's direct debit service user number, the member's stored bank details and the member's profile. If any of those are missing — most commonly bank details that were never recorded — the call fails rather than producing a partial document, so record the member's bank details before you call this.

The document lists only the memberships in the payload flagged membershipIsDirectDebit, and it is stamped with today's date, so generate it at the point the member is ready to sign.

On success you get 201 Created and the response body is a single JSON string: the URL of the generated PDF.

Endpoint

POST {base_url}/api/members/{memberId}/documents/pre-purchase-dd-mandate

{base_url} is the environment URL issued to your integration. See Authenticating with Gladstone APIs.

Path parameters

NameTypeRequiredDescription
memberIdinteger (int32)YesThe member the mandate is for — the account holder whose bank details are printed on the document. Must be greater than 0; 0 and -999 are rejected with 400. This member must also appear as one of the membersCreated[].memberId values in the body, or the call fails with 400; where a purchase created several members, call this endpoint once per member who needs a mandate.

Request body

The body is the response you received from Create members with memberships, sent back verbatim. Every field below is part of the signed payload, so changing, reordering the meaning of, or dropping any populated value invalidates signature and the request is rejected with 400 The request is invalid. Treat the whole object as opaque.

FieldTypeRequiredDescription
membersCreatedarray of objectYesOne entry per member created or updated by the purchase, copied from the membersCreated array of the create call. It must contain an entry whose memberId equals the memberId in the path, otherwise you get 400 and The given member Id is not present in the request.
membersCreated[].orderKeyinteger (int32)NoThe line reference the purchase used to tie this member to the memberships being bought, echoed back from the create call. Not used to build the mandate, but it is covered by the signature, so send it as received.
membersCreated[].memberIdinteger (int32)NoThe member this entry refers to. One of these must match the memberId in the path — that is the only check made against this array.
membersCreated[].bankAccountReferencestringNoThe reference of the bank account recorded for the member during the purchase. The mandate itself is built from the member's stored bank details rather than from this value, so it may legitimately be null here — but if the create call returned a value, send it back unchanged.
membersCreated[].salesInvoiceIdsarray of integerNoThe sales invoices raised for this member by the purchase, echoed back from the create call. Not used to build the mandate; present because it is part of the signed payload.
membershipsCreatedarray of objectYesThe memberships the purchase created, copied from the create call. At least one entry must have membershipIsDirectDebit set to true, otherwise there is nothing to mandate and the call fails with 400 and No memberships with direct debit payment were present in the request.
membershipsCreated[].memberIdinteger (int32)NoThe member the membership was allocated to. This array is filtered by membershipIsDirectDebit only — entries for other members are not excluded, so a mandate can cover memberships bought for linked members in the same transaction.
membershipsCreated[].membershipIsDirectDebitbooleanYesWhether this membership is paid by direct debit. This is the field that decides what goes on the document: only memberships with true are recorded against the generated mandate. If no entry is true the request is rejected. Do not set it yourself — it comes from the create call and is covered by the signature.
membershipsCreated[].membershipIdinteger (int32)NoThe membership the mandate will be recorded against. Collected for every entry flagged membershipIsDirectDebit and stored with the generated document, which is how the platform later matches the confirmed mandate to the paid membership.
membershipsCreated[].salesInvoiceIdsarray of integerNoThe sales invoices raised for this membership, echoed back from the create call. Not used to build the mandate; present because it is part of the signed payload.
timeStampstringYesThe UTC time the create call produced this payload, in ISO 8601 round-trip format (2026-08-19T14:03:11.1234567Z). It is rejected if it is more than ten minutes ahead of the server's clock, which is what stops a payload being minted with a future date. There is no lower bound — an old payload is not refused on age alone — but it is covered by the signature, so you cannot refresh it yourself.
signaturestringYesThe base64 HMAC-SHA512 that Gladstone put on the payload when the purchase completed. It is recomputed here over the rest of the body and compared; a mismatch is the single most common failure on this endpoint and always surfaces as 400 The request is invalid. The check is on the values, not on your formatting — whitespace and property order in what you send do not matter — but every value must survive the round trip unchanged, including nulls and empty arrays. Do not attempt to compute it yourself; the signing key is not issued to integrators.

Sample request

cURL
curl -X POST '{base_url}/api/members/{memberId}/documents/pre-purchase-dd-mandate' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "membersCreated": [
    {
      "orderKey": 1,
      "memberId": 12345,
      "bankAccountReference": "string",
      "salesInvoiceIds": [
        12345
      ]
    }
  ],
  "membershipsCreated": [
    {
      "memberId": 12345,
      "membershipIsDirectDebit": true,
      "membershipId": 12345,
      "salesInvoiceIds": [
        12345
      ]
    }
  ],
  "timeStamp": "string",
  "signature": "string"
}'

Sample response

201 Created
"string"

Errors

StatusMeaningWhen
400Bad requestsignature does not match the payload. The body is The request is invalid. Any edit to the body — including rebuilding it from your own model and losing a null or an empty array — produces this.
400Bad requesttimeStamp is more than ten minutes ahead of the server clock. The body is The time stamp of the request can not be in the future.
400Bad requestNo entry in membersCreated has a memberId matching the path. The body is The given member Id is not present in the request.
400Bad requestNo entry in membershipsCreated has membershipIsDirectDebit set to true. The body is No memberships with direct debit payment were present in the request.
400Bad requestmemberId in the path is 0 or negative. The body is {memberId} is an invalid member ID.
422Unprocessable entityThe member has no usable bank details recorded. The body is The member's bank details were not obtained successfully. Record the member's bank account before calling this.
422Unprocessable entityThe tenant has no direct debit service user number configured, or it is configured but blank. The bodies are The Service User Number was not successfully obtained. and The Service User Number obtained has a null or blank value. This is a configuration problem at the operator's end, not something you can fix in the request.
422Unprocessable entityThe member has no active membership paid by direct debit. The body is None of the active memberships returned contain a payment method of direct debit for the given member. A related variant, Error in configuration. None of the payment methods returned are configured with an EFT system specific for direct debits., means direct debit is not set up as a payment method for this tenant at all.
422Unprocessable entityThe member's profile could not be read. The body is The member's details were not obtained successfully.
422Unprocessable entityThe document could not be generated. The body is The direct debit mandate could not be generated successfully. Nothing is rolled back — the purchase and the memberships still exist, only the document is missing.
500Internal server errorAn unexpected server-side failure, including an unexpected response from one of the platform services this call depends on. Also returned when the platform's signing key is missing from configuration, in which case no request to this endpoint can succeed.
503Service unavailableOne of the services this call depends on — system configuration, member account, member profile or documents — could not be reached at all. The body is At least one of the services is unavailable. Nothing is written, so the call is safe to retry.

This page as markdown · All pages · llms.txt