# Retrieve a member's consent details

`GET /api/members/{memberId}/consent`

- **Success:** `200 OK`
- **Products:** Operator (`FOH`), Consumer (`CONSUMER`), Integrations (`INTEGRATIONS`) (any one of these products, not all)
- **Features:** Online Bookings (`ONLINEBOOK`), Online Joining (`ONLINEJOIN`), TRP Integration (`TRP`), Front of House Generic Access (`FOHGENERIC`) (any one of these features, not all)

HTML version: [Retrieve a member's consent details](https://support.gladstonesoftware.cloud/reference/members/retrieve-a-members-consent-details)

## Overview

Returns everything the platform currently holds about one member's consent: the legal agreements they have signed (online registration consent, privacy policy, terms and conditions, health commitment statement), the marketing and data-processing campaigns recorded against them, and the communication channels they have agreed to be contacted on. Call it before you send a member anything, and before you process their data on a basis that depends on their agreement.

Two things about the way consent is recorded decide how you must read this response.

**Consent is recorded by presence, not by a flag.** The platform holds one consent record per member, campaign and channel combination. Granting consent creates the record; withdrawing it deletes it. So a campaign or channel that is missing from this response means no consent is held — and that is all it means. It does not distinguish "never asked" from "asked and refused", and it is never safe to read an absence as permission.

**This is the current state only.** Every consent change is also written to a separate consent history that is never deleted, precisely so the operator can answer a GDPR audit or a subject access request. This endpoint does not expose that history, so it cannot tell you when a consent was withdrawn — only what stands today.

One structural caveat: consent is captured per member, per campaign *and* per channel, but this response flattens that. Campaigns and channels come back in separate arrays, so you cannot tell from it which channel a particular campaign consent was captured against.

Reads are separate from writes. The legal-agreement dates are updated through `PUT /api/members/{memberId}/consent`, campaign consents through `PUT /api/members/{memberId}/campaign`, and channel consents through `PUT /api/members/{memberId}/communication-channels` — the consent update endpoint cannot change campaigns or channels. Access is checked against your access token: the member ID in the path must be the member the token was issued for, or a member linked to them, such as a guardian reading a dependant's record.

## Endpoint

`GET {base_url}/api/members/{memberId}/consent`

`{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 whose consent record you want. Must be the member your access token was issued for, or a member linked to them — a guardian reading a dependant's record, for example — otherwise the request is rejected with `403 Forbidden`. |

## Sample request

```bash title="cURL"
curl -X GET '{base_url}/api/members/{memberId}/consent' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true'
```

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `memberId` | integer (int32) | The member these consent records belong to. Always the ID you supplied in the path. |
| `onlineConsentDate` | string (date-time) | When the member gave consent during online registration. `null` when no online registration consent has ever been captured for this member — for example a member created by a member of staff at a centre. |
| `onlineConsentGuardianName` | string | The guardian who gave that online consent on the member's behalf. The platform demands a guardian name when the member's date of birth puts them below the operator's configured age of consent, so a value here tells you an adult consented for a minor rather than the member consenting for themselves. Empty or `null` where no guardian was recorded. |
| `privacyPolicySignedDate` | string (date-time) | The date the member accepted the privacy policy. Dates on the consent endpoints are handled in UTC. `null` means no acceptance has been recorded, which is not a record of refusal. |
| `privacyPolicySigned` | boolean | Whether the member has accepted the privacy policy. Treat `true` as the only positive signal, and do not read `false` as a refusal. |
| `termsAndConditionsSignedDate` | string (date-time) | The date the member signed the operator's terms and conditions. Recorded in UTC. `null` means no signature has been recorded, not that the member declined. |
| `healthCommitmentStatementSignedDate` | string (date-time) | The date the member signed the health commitment statement — one of the legal agreements the platform tracks alongside the terms and conditions and the privacy policy. Recorded in UTC. `null` means no signature has been recorded. |
| `modifiedOn` | string (date-time) | When the member's consent data was last changed. |
| `createdOn` | string (date-time) | When the member's consent record was first created. |
| `campaignPreferences` | object | Groups the three sets of consent the member actively holds — marketing campaigns, data-processing campaigns and communication channels. These are maintained by their own endpoints (`PUT /api/members/{memberId}/campaign` and `PUT /api/members/{memberId}/communication-channels`) and cannot be changed through the consent update endpoint that maintains the agreement dates above. |
| `campaignPreferences.marketingCampaigns` | array of object | The marketing campaigns the member is currently opted in to. Under GDPR these are the campaigns whose lawful basis is the member's own consent, which is why the platform keeps them in a separate category from data-processing campaigns. Only opted-in campaigns appear: withdrawing consent removes the entry rather than recording a negative, so a campaign missing from this array means no consent is held for it and you must not send against it. An empty array means the member is opted in to nothing. |
| `campaignPreferences.marketingCampaigns[].campaignId` | integer (int32) | Identifies the campaign. It matches a campaign configured through `GET /api/configuration/consent/marketing-campaigns`, and it is the value you send to `PUT /api/members/{memberId}/campaign` when assigning consent. |
| `campaignPreferences.marketingCampaigns[].campaignName` | string | The name the operator gave the campaign when configuring it. |
| `campaignPreferences.marketingCampaigns[].campaignDescription` | string | The operator's configured description of the campaign. Campaign descriptions can carry per-language translations in the platform, but this response returns only the untranslated text; fetch the campaign configuration if you need a localised version. |
| `campaignPreferences.marketingCampaigns[].captureDate` | string (date-time) | The date this consent was captured from the member. If you mirror consent into your own system, this is the evidence of when the lawful basis was established, so carry it across rather than stamping your own import date. |
| `campaignPreferences.marketingCampaigns[].expiryDate` | string (date-time) | The date this consent stops applying, for campaigns the operator has configured as time-limited. `null` where the campaign has no expiry. Check the date yourself before acting on the consent: |
| `campaignPreferences.marketingCampaigns[].guardianName` | string | The guardian who gave this campaign consent on the member's behalf. The platform requires a guardian name when the member is below the operator's configured age of consent, so a value here means the lawful basis rests on the guardian's agreement rather than the member's. |
| `campaignPreferences.marketingCampaigns[].category` | string | The consent category the campaign belongs to. The platform defines exactly two, `Marketing` and `Data_Processing`; entries in this array carry the marketing one. |
| `campaignPreferences.dataCampaigns` | array of object | The data-processing campaigns recorded against the member. The platform keeps these apart from marketing campaigns because they serve a different purpose: a marketing campaign records the member's consent, whereas a data-processing campaign records the GDPR Article 6 lawful basis being relied on for a processing activity. |
| `campaignPreferences.dataCampaigns[].campaignId` | integer (int32) | Identifies the data-processing campaign. It matches a campaign configured through `GET /api/configuration/consent/data-processing`. |
| `campaignPreferences.dataCampaigns[].campaignName` | string | The name the operator gave the data-processing campaign when configuring it. |
| `campaignPreferences.dataCampaigns[].campaignDescription` | string | The operator's configured description of the data-processing campaign, in its untranslated form. |
| `campaignPreferences.dataCampaigns[].captureDate` | string (date-time) | The date this record was captured against the member — your evidence of when the lawful basis was established. |
| `campaignPreferences.dataCampaigns[].expiryDate` | string (date-time) | The date this record stops applying, for campaigns configured as time-limited. `null` where the campaign has no expiry. |
| `campaignPreferences.dataCampaigns[].guardianName` | string | The guardian recorded against this entry, present where the member was below the operator's configured age of consent when it was captured. |
| `campaignPreferences.dataCampaigns[].category` | string | The consent category the campaign belongs to. Entries in this array carry `Data_Processing`, as opposed to the `Marketing` category used by the array above. |
| `campaignPreferences.communicationTypes` | array of object | The channels the member has agreed to be contacted on. As with campaigns, membership of this array *is* the opt-in — removing a channel deletes the entry — so a channel that is absent means no agreement is held for it, whether or not you hold a working address or number for the member on that channel. An empty array means the member has agreed to no channel at all. |
| `campaignPreferences.communicationTypes[].channelId` | string | The channel's configured code — `EMAIL`, `SMS`, `TELEPHONE` and `POST` are the usual ones, but the set is per-operator configuration and operators can add their own. Read the live list from `GET /api/configuration/consent/communication-channels` and match against that rather than hard-coding values. |
| `campaignPreferences.communicationTypes[].channelName` | string | The name the operator gave the channel when configuring it. |
| `campaignPreferences.communicationTypes[].captureDate` | string (date-time) | The date the member's agreement to be contacted on this channel was captured. |

## Sample response

```json title="200 OK"
{
  "memberId": 12345,
  "onlineConsentDate": "2026-08-14T19:00:00Z",
  "onlineConsentGuardianName": "string",
  "privacyPolicySignedDate": "2026-08-14T19:00:00Z",
  "privacyPolicySigned": true,
  "termsAndConditionsSignedDate": "2026-08-14T19:00:00Z",
  "healthCommitmentStatementSignedDate": "2026-08-14T19:00:00Z",
  "modifiedOn": "2026-08-14T19:00:00Z",
  "createdOn": "2026-08-14T19:00:00Z",
  "campaignPreferences": {
    "marketingCampaigns": [
      {
        "campaignId": 12345,
        "campaignName": "string",
        "campaignDescription": "string",
        "captureDate": "2026-08-14T19:00:00Z",
        "expiryDate": "2026-08-14T19:00:00Z",
        "guardianName": "string",
        "category": "string"
      }
    ],
    "dataCampaigns": [
      {
        "campaignId": 12345,
        "campaignName": "string",
        "campaignDescription": "string",
        "captureDate": "2026-08-14T19:00:00Z",
        "expiryDate": "2026-08-14T19:00:00Z",
        "guardianName": "string",
        "category": "string"
      }
    ],
    "communicationTypes": [
      {
        "channelId": "string",
        "channelName": "string",
        "captureDate": "2026-08-14T19:00:00Z"
      }
    ]
  }
}
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | |
| `404` | Not found | |
| `500` | Internal server error | |
