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

# Opt Out of Marketing

> Record that a contact asked to stop receiving marketing messages

Use this endpoint whenever a contact tells **you** they want to stop receiving marketing: a reply to
your own bot, a support ticket, a form on your site. Minimo then stops marketing sends to that contact
exactly as if they had used an unsubscribe link or told Minimo's AI assistant.

> [!NOTE]
>
> Only **marketing** consent is withdrawn. Transactional and utility messages (order updates, account emails, approved
> utility WhatsApp templates) keep working.

## Which channels are withdrawn

The result depends on your company's **opt-out scope** (Settings → Contacts):

| Scope | Effect |
| - | - |
| `global` | Default. Withdraws WhatsApp, email and SMS marketing for the contact and every contact with the same phone or email. |
| `per_channel` | Withdraws only the `channel` the contact asked on. |

The response tells you which scope was applied and which channels were withdrawn, so you can confirm
it to the contact in your own words (for example "Done, you won't receive offers from us any more").

## Identifying the contact

Send **exactly one** of:

* `phone`: E.164 or digits only. With a WhatsApp bot, pass the `contact.phone` from the [inbound
  webhook envelope](https://docs.minimo.it/api-reference/whatsapp-transport/webhooks.md). `channel` defaults to `whatsapp`.
* `email`: case-insensitive. `channel` defaults to `email`.
* `contactId`: the Minimo contact id. `channel` is required.

The contact is always looked up inside the company that owns your API key.

## Permissions

Any API key with the `subscribe`, `transactional` or `whatsapp` permission can call it. A
WhatsApp-only key, the one used by bots connected through [Connect Your
Bot](https://docs.minimo.it/api-reference/whatsapp-transport/overview.md), is enough.

## Common Errors

| Status | Cause | Solution |
| - | - | - |
| `400` | No identifier, several identifiers, or `contactId` without `channel` | Send exactly one of `phone`, `email`, `contactId` |
| `401` | Missing or expired key, or a key without `subscribe`, `transactional` or `whatsapp` | Use a valid key with one of those permissions |
| `404` | No contact with that phone, email or id in your company | Nothing to withdraw: the contact never received marketing from Minimo |

## Related

* **[Handle unsubscribe requests in your bot](https://docs.minimo.it/api-reference/whatsapp-transport/opt-out.md)**: end-to-end example for a WhatsApp bot
* **[Create or Update Contact](https://docs.minimo.it/api-reference/core-data/contacts/upsert.md)**: set consent explicitly per channel with `marketingConsent`
* **MCP**: agents connected to Minimo's MCP server can do the same with the `minimo_contact_opt-out` tool ([Connect your agent](https://docs.minimo.it/guides/connect-your-agent.md))


## OpenAPI

````yaml post /public/v1/contacts/opt-out
openapi: 3.1.0
info:
  title: API Documentation
  description: Documentation for transactional and subscribe APIs
  version: 1.0.0
servers:
  - url: https://app.minimo.it
security:
  - bearerAuth: []
paths:
  /public/v1/contacts/opt-out:
    servers:
      - url: https://api.minimo.it
    post:
      summary: Opt a contact out of marketing
      description: >-
        Withdraws a contact's marketing consent when they ask to unsubscribe,
        for example when your own WhatsApp bot (connected through the inbound
        webhook) detects "please stop sending me offers". Identify the contact
        with exactly one of `phone`, `email` or `contactId`. The company's
        opt-out scope is applied exactly as Minimo's AI assistant does it:
        `global` withdraws WhatsApp, email and SMS marketing for the contact and
        every identity-linked contact; `per_channel` withdraws only the channel
        the contact asked on. Transactional and utility messages are never
        affected. Idempotent. Accepts API keys with the `subscribe`,
        `transactional` or `whatsapp` permission.
      operationId: optOutContact
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                phone:
                  type: string
                  description: >-
                    Phone number, E.164 or digits only (e.g. the `contact.phone`
                    of the inbound webhook envelope).
                  examples:
                    - '393391234567'
                email:
                  type: string
                  format: email
                  description: Email address of the contact (case-insensitive).
                contactId:
                  type: integer
                  description: Minimo contact id. Requires `channel`.
                channel:
                  type: string
                  enum:
                    - whatsapp
                    - email
                    - sms
                  description: >-
                    Channel the contact asked on. Defaults to `whatsapp` for
                    `phone` and `email` for `email`; required with `contactId`.
                reason:
                  type: string
                  maxLength: 500
                  description: >-
                    Optional context for the consent audit trail, e.g. the
                    customer's message.
            examples:
              whatsappBot:
                summary: A WhatsApp bot honouring "stop"
                value:
                  phone: '393391234567'
                  reason: 'Customer wrote: "smettete di scrivermi"'
              emailReply:
                summary: An email reply asking to unsubscribe
                value:
                  email: customer@example.com
      responses:
        '200':
          description: Opt-out recorded
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      contactId:
                        type: integer
                        examples:
                          - 12345
                      channel:
                        type: string
                        enum:
                          - whatsapp
                          - email
                          - sms
                      scope:
                        type: string
                        enum:
                          - global
                          - per_channel
                          - intent
                        description: The company's opt-out scope that was applied.
                      revokedChannels:
                        type: array
                        items:
                          type: string
                        description: >-
                          Every marketing channel whose consent is now
                          withdrawn.
                        examples:
                          - - whatsapp
                            - email
                            - sms
                      affectedContactIds:
                        type: array
                        items:
                          type: integer
                        description: >-
                          Every contact the opt-out reached (identity-linked
                          contacts under `global`).
        '400':
          description: Zero or several identifiers, or `contactId` without `channel`
        '401':
          description: >-
            Missing, expired or invalid API key, or a key without the
            `subscribe`, `transactional` or `whatsapp` permission
        '404':
          description: No contact with that phone, email or id in your company
      security:
        - bearerAuth: []
      x-codeSamples:
        - lang: Python
          source: |-
            import requests

            res = requests.post(
                'https://api.minimo.it/public/v1/contacts/opt-out',
                headers={'Authorization': 'Bearer {{BEARER_TOKEN}}'},
                json={'phone': '393391234567', 'reason': 'Customer asked to stop'},
            )
            print(res.json())
        - lang: JavaScript
          source: >-
            const res = await
            fetch('https://api.minimo.it/public/v1/contacts/opt-out', {
              method: 'POST',
              headers: {
                'Authorization': 'Bearer {{BEARER_TOKEN}}',
                'Content-Type': 'application/json',
              },
              body: JSON.stringify({ phone: '393391234567', reason: 'Customer asked to stop' }),
            });

            const { data } = await res.json();

            console.log(data.revokedChannels);
        - label: CLI
          lang: cURL
          source: |-
            curl --request POST \
              --url 'https://api.minimo.it/public/v1/contacts/opt-out' \
              --header 'Authorization: Bearer {{BEARER_TOKEN}}' \
              --header 'Content-Type: application/json' \
              --data '{"phone": "393391234567", "reason": "Customer asked to stop"}'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: mn-API_CLIENT_ID-API_KEY

````

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