# DMCCA required API updates

> Changes your integration must make to comply with the Digital Markets, Competition and Consumers Act.

HTML version: [DMCCA required API updates](https://support.gladstonesoftware.cloud/guides/dmcca-required-api-updates)

Updates to the API calls to provide information required for DMCCA regulations.

For customers using our APIs to build their own member joining journey, or membership cancellation flow, these are the updates to our endpoints that will provide required information according to the legislation. This will be organised by updates information for: Invitation to purchase, pre-contract information, and cancellations.

This guide currently covers invitation to purchase and self-service cancellation. Pre-contract information will be added when it is available.

## Invitation to purchase

An invitation to purchase is any stage where you provide the details and price of a membership and ask the consumer to take a step towards purchasing.

You must provide the following detail on any page with an invitation to purchase:

* **The main characteristics of the product** - Provided with the tag description

* **Total price of the product.** This can be either:
  * The total price over the life of the membership
  * The monthly price and the number of minimum months, plus any pro-rata or one-off costs

* **The existence of the right to cancel** where it exists - Can be taken from whether the membership is recurring in the pricing call and/or a cooling off period.

* **Trader details** - Provided with the system configuration call
  * The identity of the trader
  * The business or service address
  * The business email address

This information is fully available now through APIs: main characteristics of the product, identity of the trader, and business email address.

This information is partially available: total price, existence of the right to cancel.

Information which is coming soon: business or service address, remaining parts of the total price and right to cancel.

### Main characteristics of the product

In Go Join we retrieve the main characteristics of the product from the membership type tag description under the Membership Facilities tag group. This gives a description of the type of membership available they are purchasing.

Use the [POST/api/memberships/membership-types-by-tag-group](../reference/joining/get-membership-types-grouped-by-tag.md) to retrieve the membership types, the tag groups they are available in, and their description.

Use `groupTag.description` for the main characteristics of the product.

```json membership-types-by-tag-group reduced
[
    {
        "groupTag": {
            "id": 11,
            "key": "Premium",
            "name": "Premium",

            "description": "Unlimited Access to our up-to-date gyms.",
            "sortOrder": 4,
            "isSecondary": false,
            "translations": []
        },
        "membershipTypes": [
            {
                "id": "SSUBRC0001",
                "description": "Premium Adult R C P",
                "applyToLinks": false,
                "minAge": null,
                "maxAge": null,
                "imageUrl": null,
                "minimumContractLength": {
                    "length": 12,
                    "lengthType": "Monthly",
                    "periodType": "ByPayment"
                },
                "renewal": null,
                "priceLevelId": "ADULT",
                "prices": {
                    "headlinePrice": {
                        "amount": "30.00",
                        "currency": "GBP",
                        "discount": null
                    },
                    "startUpFee": {
                        "amount": "0.00",
                        "currency": "GBP",
                        "discount": null
                    }
                },
                "tagGroups": [],
                "translations": []
            }
        ]
    }
]
```

### Total price of the product

The total price of the product is calculated using the regular recurring price, the minimum contract term, and the pay now price.

For a recurring membership in Go Join we display the recurring price, the minimum number of payments, and the pay now price (if different from the recurring price) with details of what that includes, e.g. one-off fee and/or pro-rata month.

For a cash membership we simply display the total price including any one-off fees.

Details required to display the total price are provided in the [POST/api/memberships/membership-types-by-tag-group](../reference/joining/get-membership-types-grouped-by-tag.md) and `POST /api/pricing/memberships` endpoints.

This portal does not yet publish a reference page for `POST /api/pricing/memberships`. The examples below show the pricing fields used by this guide, but the endpoint reference still needs source confirmation before publication.

The **POST/api/memberships/membership-types-by-tag-group** call provides the minimum contract term in the membership types object. This allows you to display the total number of months the member will be contracted to pay for along with the prices in the following call.

Use `membershipTypes[].minimumContractLength` for the number of payments required by the contract.

```json membership-types-by-tag-group reduced
[
    {
        "groupTag": {
            "id": 11,
            "key": "Premium",
            "name": "Premium",
            "description": "Unlimited Access to our up-to-date gyms.",
            "sortOrder": 4,
            "isSecondary": false,
            "translations": []
        },
        "membershipTypes": [
            {
                "id": "SSUBRC0001",
                "description": "Premium Adult R C P",
                "applyToLinks": false,
                "minAge": null,
                "maxAge": null,
                "imageUrl": null,

                "minimumContractLength": {
                    "length": 12,
                    "lengthType": "Monthly",
                    "periodType": "ByPayment"
                },
                "renewal": null,
                "priceLevelId": "ADULT",
                "prices": {
                    "headlinePrice": {
                        "amount": "30.00",
                        "currency": "GBP",
                        "discount": null
                    },
                    "startUpFee": {
                        "amount": "0.00",
                        "currency": "GBP",
                        "discount": null
                    }
                },
                "tagGroups": [],
                "translations": []
            }
        ]
    }
]
```

The **POST/api/pricing/memberships** call provides the pricing information. This should be gathered from the membership object rather than the overview to ensure it's specific to the membership type.

Use `memberships[].pricing.now.totalPrice` for the amount to pay today. Use `memberships[].pricing.now.breakdown[]` for the payment types included today, such as regular, pro-rata or one-off payments. Use `memberships[].pricing.recurring` for the amount and frequency of recurring payments.

```json pricing/memberships reduced
{
    "siteId": "WEST",
    "promotionCode": null,
    "overview": {},
    "memberships": [
        {
            "orderKey": 1,
            "id": "AD45A-RCP1",
            "description": "O/p Adu All Rcp",
            "coolingOffPeriod": 14,
            "translations": [
                {
                    "type": "name",
                    "culture": "cy-gb",
                    "text": "O/p Adu All Rcp WelshName"
                }
            ],
            "startDate": "2027-01-14T00:00:00Z",
            "endDate": "2027-02-13T00:00:00Z",
            "pricing": {

                "now": {
                    "totalPrice": {
                        "amount": "26.00",
                        "currency": "GBP",
                        "discount": null
                    },

                    "breakdown": [
                        {
                            "priceLevelId": "STAND",
                            "productId": "AD45A-RCP1",
                            "type": "regular",
                            "description": "O/p Adu All Rcp",
                            "translations": [],
                            "price": {
                                "amount": "25.00",
                                "currency": "GBP",
                                "discount": null
                            }
                        },
                        {
                            "priceLevelId": "STAND",
                            "productId": "ADMIN-15",
                            "type": "one-off",
                            "description": "Joining Fee",
                            "translations": [],
                            "price": {
                                "amount": "1.00",
                                "currency": "GBP",
                                "discount": null
                            }
                        }
                    ]
                },

                "recurring": {
                    "membershipId": null,
                    "headlinePrice": {
                        "amount": "25.00",
                        "currency": "GBP",
                        "discount": null
                    },
                    "frequency": "Monthly"
                }
            }
        }
    ],
    "timeStamp": "2026-01-26T09:43:21.0005666Z",
    "signature": "Avl79+nY/tLsR6JbnShgao6gD2wXzzs00vL9XOvLBQZ2KumdQbT3Q/mfo1Fs+qHQXdRIjTI8PK4EaOKdC5Ddsw=="
}
```

### Existence of the right to cancel

You must inform the member if they have a right to cancel during the invitation to purchase. You do not need to provide details of how to cancel as that is done at a later stage.

There are two types of cancellation rights for memberships:

1. During the cooling-off period - Any membership can be cancelled during the cooling off period if it exists. The DMCCA will enforce a minimum 14 day cancellation period.\
   E.g. an annual up-front membership.
2. Once any minimum term is complete for an auto-renewing membership - This applies to any recurring membership.\
   E.g. a monthly membership with or without a minimum term.

Due to this, we have two values to check in endpoints to confirm whether any right to cancel exists. In Go Join we also clarify whether this is only during the cooling-off period or additional after any minimum period.

The **POST/api/pricing/memberships** call provides the cooling-off period in the membership object to indicate whether the selected membership has a cooling off period during which the membership can be cancelled. It also provides whether the membership is auto-renewing or a recurring membership; this indicates whether it can be cancelled after the cooling off period or if it will end on its own and therefore does not need to be cancelled.

Use `memberships[].coolingOffPeriod` for the cooling-off period. Use `memberships[].pricing.recurring` to identify whether the membership is auto-renewing or up-front only.

```json pricing/memberships reduced
{
    "siteId": "WEST",
    "promotionCode": null,
    "overview": {},
    "memberships": [
        {
            "orderKey": 1,
            "id": "AD45A-RCP1",
          	"description": "O/p Adu All Rcp",

            "coolingOffPeriod": 14,
            "translations": [
                {
                    "type": "name",
                    "culture": "cy-gb",
                    "text": "O/p Adu All Rcp WelshName"
                }
            ],
            "startDate": "2027-01-14T00:00:00Z",
            "endDate": "2027-02-13T00:00:00Z",
            "pricing": {
                "now": {
                    "totalPrice": {
                        "amount": "26.00",
                        "currency": "GBP",
                        "discount": null
                    },
                  "breakdown": [
                        {
                            "priceLevelId": "STAND",
                            "productId": "AD45A-RCP1",
                            "type": "regular",
                            "description": "O/p Adu All Rcp",
                            "translations": [],
                            "price": {
                                "amount": "25.00",
                                "currency": "GBP",
                                "discount": null
                            }
                        },
                        {
                            "priceLevelId": "STAND",
                            "productId": "ADMIN-15",
                            "type": "one-off",
                            "description": "Joining Fee",
                            "translations": [],
                            "price": {
                                "amount": "1.00",
                                "currency": "GBP",
                                "discount": null
                            }
                        }
                    ]
                },

                "recurring": {
                    "membershipId": null,
                    "headlinePrice": {
                        "amount": "25.00",
                        "currency": "GBP",
                        "discount": null
                    },
                    "frequency": "Monthly"
                }
            }
        }
    ],
    "timeStamp": "2026-01-26T09:43:21.0005666Z",
    "signature": "Avl79+nY/tLsR6JbnShgao6gD2wXzzs00vL9XOvLBQZ2KumdQbT3Q/mfo1Fs+qHQXdRIjTI8PK4EaOKdC5Ddsw=="
}
```

#### Optional

The [**POST/api/memberships/membership-types-by-tag-group**](../reference/joining/get-membership-types-grouped-by-tag.md) call provides the minimum contract term. This is optional to include when the membership can be cancelled if there is a right and there is a minimum term. In Go Join, we let members know that they can cancel after the minimum term if it exists.

Use `membershipTypes[].minimumContractLength` to identify the period after which a member can cancel.

```json membership-types-by-tag-group reduced
[
    {
        "groupTag": {
            "id": 11,
            "key": "Premium",
            "name": "Premium",
            "description": "Unlimited Access to our up-to-date gyms.",
            "sortOrder": 4,
            "isSecondary": false,
            "translations": []
        },
        "membershipTypes": [
            {
                "id": "SSUBRC0001",
                "description": "Premium Adult R C P",
                "applyToLinks": false,
                "minAge": null,
                "maxAge": null,
                "imageUrl": null,

                "minimumContractLength": {
                    "length": 12,
                    "lengthType": "Monthly",
                    "periodType": "ByPayment"
                },
                "renewal": null,
                "priceLevelId": "ADULT",
                "prices": {
                    "headlinePrice": {
                        "amount": "30.00",
                        "currency": "GBP",
                        "discount": null
                    },
                    "startUpFee": {
                        "amount": "0.00",
                        "currency": "GBP",
                        "discount": null
                    }
                },
                "tagGroups": [],
                "translations": []
            }
        ]
    }
]
```

### Trader details

All of these details are or will be available using the [GET/api/configuration/system/groups](../reference/configuration/retrieves-system-configuration-settings-grouped-by-configuration-group-ids.md) call. Here are the details mapped to the groups to pass into the call and the unique config key to identify them.

| Trader detail               | Config Key              | Group |
| :-------------------------- | :---------------------- | :---- |
| Identity of the trader      | "Operator\_TradingName" | 13    |
| Business email address      | "Join\_HelpEmail"       | 11    |
| Business or service address | "Join\_BusinessAddress" | 11    |

## Cancellations

If you build your own account area for members, two endpoints let a member cancel an auto-renewing membership online, or cancel a membership during its cooling-off period, without contacting the operator.

1. Call [Get member memberships and payment information](../reference/members/get-member-memberships-and-payment-information.md) for the signed-in member. Each membership carries a `cancellation` object.
2. Use `cancellation.allowed` to decide whether to offer a cancel option for that membership, and `cancellation.reasonID` to choose what to tell the member. When `allowed` is `false`, `reasonID` says why: for example `2` when someone else pays for the membership, so only they can cancel it.
3. When `reasonID` is `7`, the membership is inside its cooling-off period and cancelling ends it immediately. When it is `8`, cancelling stops the membership renewing and the member keeps it until a date they choose from `cancellation.cancellationDates`. Each date is the last day they keep access, and the list already accounts for the member's notice period and any minimum term.
4. Show the member the outcome and ask them to confirm, then call [Cancel a membership for the paying member](../reference/members/cancel-a-membership-for-the-paying-member.md) with the chosen date, or no date for an immediate cancellation.

```json memberships reduced
[
    {
        "id": "DANSKESUB",
        "membershipRef": 3014,
        "paidByMember": {
            "id": 1003,
            "name": "Banky McDanske-Face"
        },
        "cancellation": {
            "allowed": true,
            "reason": "This membership will stop renewing and remain active until its cancellation takes effect",
            "reasonID": 8,
            "cancellationDates": ["2026-10-16", "2026-11-16", "2026-12-16"]
        }
    }
]
```

After a successful cancellation the platform emails the member a confirmation and notifies the operator's staff. Neither endpoint issues a refund: where a member cancelling in the cooling-off period is owed money, the operator's staff process it, so do not tell the member a refund has been made.
