Hellou AI Marketing Consent API

The Marketing Consent API from Hellou AI — 3 operation(s) for marketing consent.

GitHub OpenAPI

Operations 5

GET /api/v1/accounts/{account_id}/contacts/{id}/marketing_consent Get a contact's marketing consent #
POST /api/v1/accounts/{account_id}/contacts/{id}/marketing_consent Record a contact's marketing consent #
DELETE /api/v1/accounts/{account_id}/contacts/{id}/marketing_consent Clear a contact's marketing consent #
GET /api/v1/accounts/{account_id}/marketing_consents List marketing consents #
POST /api/v1/accounts/{account_id}/marketing_consents/bulk Record marketing consent in bulk #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/hellou-ai:hellou-ai-marketing-consent-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

hellou-ai-marketing-consent-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: HellouOne Marketing Consent API
  version: 1.0.0
  description: 'The HellouOne REST API: everything the dashboard does, available to your

    own systems — CRMs, bots, BI tools and back-office automation.'
  termsOfService: https://hellou.ai/en/legal/terms/
  contact:
    name: HellouOne support
    email: support@hellou.ai
servers:
- url: https://one.hellou.ai
  description: HellouOne cloud
security:
- userApiKey: []
tags:
- name: Marketing Consent
paths:
  /api/v1/accounts/{account_id}/contacts/{id}/marketing_consent:
    parameters:
    - $ref: '#/components/parameters/account_id'
    - name: id
      in: path
      required: true
      description: ID of the contact
      schema:
        type: integer
    get:
      tags:
      - Marketing Consent
      operationId: getContactMarketingConsent
      summary: Get a contact's marketing consent
      description: 'The contact''s recorded marketing consent on one channel. When nothing is

        recorded the response still answers 200, with `status`, `source` and

        `recorded_at` null and no `id`: no record is a state of its own, not an

        opt-in.


        Available to administrators and agents.


        **Requires feature:** `whatsapp_campaigns`'
      x-required-feature: whatsapp_campaigns
      parameters:
      - name: channel
        in: query
        required: false
        description: Consent channel. Defaults to `whatsapp`.
        schema:
          type: string
          enum:
          - whatsapp
          - sms
          - email
          default: whatsapp
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/marketing_consent'
        '400':
          description: Unknown `channel`.
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not_found'
    post:
      tags:
      - Marketing Consent
      operationId: setContactMarketingConsent
      summary: Record a contact's marketing consent
      description: 'Records an opt-in or opt-out for the contact, replacing any earlier record

        on that channel. Use it to honour a request made outside the channel, for

        example on a phone call. The source, the acting user and the timestamps are

        set by the server: `api` when you call with an access token, `agent` from the

        dashboard. `status` must be exactly `opted_in` or `opted_out`. A WhatsApp opt-out excludes the contact from

        WhatsApp campaigns.


        The request parameters are top-level, not wrapped.


        Available to administrators and agents. Turning a recorded opt-out back into

        an opt-in is administrator-only: an agent gets `403`.


        **Requires feature:** `whatsapp_campaigns`'
      x-required-feature: whatsapp_campaigns
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/marketing_consent_create_payload'
      responses:
        '200':
          description: Recorded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/marketing_consent'
        '400':
          description: Unknown `channel`.
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not_found'
        '422':
          description: '`status` is missing or not `opted_in`/`opted_out` (`reason: invalid_status`), or the record is invalid.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error_message'
    delete:
      tags:
      - Marketing Consent
      operationId: clearContactMarketingConsent
      summary: Clear a contact's marketing consent
      description: 'Deletes the consent record, returning the contact to "no recorded consent"

        on that channel. This is not an opt-in; the account''s consent mode decides

        what no record means. Succeeds even when there was no record.


        **Administrators only.**


        **Requires feature:** `whatsapp_campaigns`'
      x-required-feature: whatsapp_campaigns
      parameters:
      - name: channel
        in: query
        required: false
        description: Consent channel. Defaults to `whatsapp`.
        schema:
          type: string
          enum:
          - whatsapp
          - sms
          - email
          default: whatsapp
      responses:
        '204':
          description: Cleared.
        '400':
          description: Unknown `channel`.
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not_found'
  /api/v1/accounts/{account_id}/marketing_consents:
    parameters:
    - $ref: '#/components/parameters/account_id'
    get:
      tags:
      - Marketing Consent
      operationId: listMarketingConsents
      summary: List marketing consents
      description: 'Every recorded marketing consent in the account, with its contact. Newest change first, or —

        with `updated_since` and then `cursor` — every change since a moment, oldest first, until

        `meta.next_cursor` is `null`.


        Contacts with no record are not listed, and a cleared consent deletes its record: to learn about

        clears, subscribe to the `marketing_consent_changed` webhook (`action: cleared`).


        **Administrators only.**


        **Requires feature:** `whatsapp_campaigns`'
      x-required-feature: whatsapp_campaigns
      parameters:
      - name: status
        in: query
        schema:
          type: string
          enum:
          - opted_in
          - opted_out
      - name: channel
        in: query
        schema:
          type: string
          enum:
          - whatsapp
          - sms
          - email
      - name: source
        in: query
        schema:
          type: string
          enum:
          - signup_form
          - csv_import
          - inbound_keyword
          - opt_out_button
          - agent
          - api
          - conversation
          - admin_bulk
          - lead_ad
          - inbound_intent
          - voice_call
      - name: page
        in: query
        description: Page number, from 1. Ignored when syncing.
        schema:
          type: integer
          minimum: 1
          default: 1
      - name: per_page
        in: query
        description: Records per response. Values above 500 are treated as 500.
        schema:
          type: integer
          minimum: 1
          maximum: 500
          default: 25
      - name: updated_since
        in: query
        description: Sync mode. Only records created or changed at or after this ISO 8601 timestamp, oldest change first.
        schema:
          type: string
          format: date-time
      - name: cursor
        in: query
        description: Sync mode. The `meta.next_cursor` from the previous response.
        schema:
          type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/marketing_consent_list'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '422':
          description: A filter, `updated_since` or `cursor` cannot be read (`reason`, for example `invalid_source`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error_message'
  /api/v1/accounts/{account_id}/marketing_consents/bulk:
    parameters:
    - $ref: '#/components/parameters/account_id'
    post:
      tags:
      - Marketing Consent
      operationId: bulkRecordMarketingConsents
      summary: Record marketing consent in bulk
      description: 'Records up to 500 opt-ins and opt-outs in one call — for example to import the consent list your

        CRM or web forms collected. Each row names an **existing** contact by `contact_id` or by `phone`

        (any common format; it is matched in E.164). Contacts are never created.


        Rows are independent: each gets a `result` — `recorded`, `unchanged` (the contact already had

        that status; its original record and evidence are kept), `not_found` or `invalid` — and one bad

        row never stops the others. The source is `api` with an access token, `admin_bulk` from the

        dashboard.


        **Administrators only.**


        **Requires feature:** `whatsapp_campaigns`'
      x-required-feature: whatsapp_campaigns
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/marketing_consent_bulk_payload'
      responses:
        '200':
          description: One result per row, in order.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/marketing_consent_bulk_result'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '422':
          description: '`consents` is missing, empty, longer than 500 rows, or not a list of objects.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error_message'
components:
  schemas:
    marketing_consent:
      type: object
      description: 'A contact''s marketing consent on one channel. Consent has three states: an

        explicit opt-in, an explicit opt-out, or no record at all (`status` null),

        which the account''s consent mode interprets.

        '
      properties:
        id:
          type: integer
          description: Absent when there is no record.
        contact_id:
          type: integer
        inbox_id:
          type:
          - integer
          - 'null'
          description: Inbox the consent was collected through, when known. Absent when there is no record.
        channel:
          type: string
          enum:
          - whatsapp
          - sms
          - email
        status:
          type:
          - string
          - 'null'
          enum:
          - opted_in
          - opted_out
          - null
        source:
          type:
          - string
          - 'null'
          enum:
          - signup_form
          - csv_import
          - inbound_keyword
          - opt_out_button
          - agent
          - api
          - conversation
          - admin_bulk
          - lead_ad
          - inbound_intent
          - voice_call
          - null
          description: How the consent was recorded. Set by the server; consent recorded with an access token is `api`, from the dashboard `agent`, by bulk import from the dashboard `admin_bulk`, and an opt-out the AI classification read in the customer's own words (opt-out detection in `enforce`) is `inbound_intent`, and on an AI call (`voice_call`) a spoken opt-out (one opt-out covers voice and WhatsApp marketing) or the yes the contact gave to the WhatsApp follow-up offer.
        recorded_at:
          type:
          - string
          - 'null'
          format: date-time
          description: When the consent was last recorded.
        last_changed_at:
          type:
          - string
          - 'null'
          format: date-time
          description: When the status last changed. Absent when there is no record.
      required:
      - contact_id
      - channel
      - status
      - source
      - recorded_at
    marketing_consent_list:
      type: object
      properties:
        payload:
          type: array
          items:
            allOf:
            - $ref: '#/components/schemas/marketing_consent'
            - type: object
              properties:
                updated_at:
                  type: string
                  format: date-time
                  description: Last change, to the microsecond.
                contact:
                  type: object
                  properties:
                    id:
                      type: integer
                    name:
                      type:
                      - string
                      - 'null'
                    phone_number:
                      type:
                      - string
                      - 'null'
                    email:
                      type:
                      - string
                      - 'null'
                  required:
                  - id
              required:
              - updated_at
              - contact
        meta:
          type: object
          properties:
            per_page:
              type: integer
            count:
              type: integer
              description: Not sent when syncing.
            current_page:
              type: integer
              description: Not sent when syncing.
            next_cursor:
              type:
              - string
              - 'null'
              description: Sync mode only. Pass as `cursor`; `null` when there is nothing more.
          required:
          - per_page
      required:
      - payload
      - meta
    marketing_consent_bulk_result:
      type: object
      properties:
        payload:
          type: array
          items:
            type: object
            properties:
              index:
                type: integer
                description: Position of the row in the request, from 0.
              result:
                type: string
                enum:
                - recorded
                - unchanged
                - not_found
                - invalid
              contact_id:
                type:
                - integer
                - 'null'
              error:
                type:
                - string
                - 'null'
              consent:
                oneOf:
                - $ref: '#/components/schemas/marketing_consent'
                - type: 'null'
            required:
            - index
            - result
            - contact_id
            - error
            - consent
        meta:
          type: object
          description: How many rows ended in each result.
          properties:
            recorded:
              type: integer
            unchanged:
              type: integer
            not_found:
              type: integer
            invalid:
              type: integer
          required:
          - recorded
          - unchanged
          - not_found
          - invalid
      required:
      - payload
      - meta
    error_message:
      type: object
      description: An error with a human-readable message.
      properties:
        error:
          type: string
          description: What went wrong.
        reason:
          type: string
          description: Machine-readable cause, when there is one (for example `feature_disabled`).
      required:
      - error
    marketing_consent_create_payload:
      type: object
      properties:
        status:
          type: string
          enum:
          - opted_in
          - opted_out
          description: '`opted_out` records an opt-out. Any other value, or none, records an opt-in.

            '
        channel:
          type: string
          enum:
          - whatsapp
          - sms
          - email
          default: whatsapp
        note:
          type: string
          description: Free-text evidence, for example "asked to stop on a call". Stored with the record, not returned.
      example:
        status: opted_out
        note: Asked on the phone not to receive promotions
    marketing_consent_bulk_payload:
      type: object
      properties:
        consents:
          type: array
          minItems: 1
          maxItems: 500
          items:
            type: object
            properties:
              contact_id:
                type: integer
                description: The contact's ID. Use this or `phone`.
              phone:
                type: string
                description: The contact's phone number, in any common format.
              status:
                type: string
                enum:
                - opted_in
                - opted_out
              channel:
                type: string
                enum:
                - whatsapp
                - sms
                - email
                default: whatsapp
              note:
                type: string
                maxLength: 500
                description: Kept with the record as evidence (for example the form it came from).
            required:
            - status
      required:
      - consents
  responses:
    unauthorized:
      description: Missing or invalid `api_access_token`, or a bot token on an endpoint bots cannot use.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/error_message'
    forbidden:
      description: 'Not allowed: the user''s role does not permit it, the feature is not enabled

        for the account (`reason: feature_disabled`), or the account is read-only.

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/error_message'
    not_found:
      description: The resource does not exist in this account.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/error_message'
  parameters:
    account_id:
      in: path
      name: account_id
      required: true
      description: The numeric ID of the account
      schema:
        type: integer
  securitySchemes:
    userApiKey:
      type: apiKey
      in: header
      name: api_access_token
      description: 'A user''s access token, from **Profile settings → Access token** in the dashboard.

        Requests act with that user''s role: administrators reach everything in their

        account, agents only what their role and visibility settings allow.

        '
    agentBotApiKey:
      type: apiKey
      in: header
      name: api_access_token
      description: 'An agent bot''s access token, shown to administrators on the bot''s settings page.

        Bot tokens reach a limited set of conversation and message endpoints.

        '
    platformAppApiKey:
      type: apiKey
      in: header
      name: api_access_token
      description: 'A platform app token, issued by the installation operator. Used to provision

        accounts, users, account memberships and agent bots.

        '
    connectorInvokeToken:
      type: http
      scheme: bearer
      description: 'A connector''s invoke token (`hci_…`), sent as `Authorization: Bearer <token>`.

        Each connector install has its own; it is rotated whenever the connector is

        reconnected or disconnected, so a stale copy stops working.

        '
x-tagGroups:
- name: Guides
  tags:
  - Introduction
  - Authentication
  - Errors
  - Pagination
  - Rate limits
  - Webhook events
- name: Webhook payloads
  tags:
  - Event payloads
- name: Platform
  tags:
  - Accounts
  - Account Users
  - AgentBots
  - Users
- name: Application
  tags:
  - Account AgentBots
  - Agents
  - Automation Rule
  - Campaigns
  - Canned Responses
  - Contacts
  - Contact Labels
  - Conversation Assignment
  - Conversation Labels
  - Conversations
  - Custom Attributes
  - Custom Filters
  - Help Center
  - Inboxes
  - Integrations
  - Macros
  - Messages
  - Profile
  - Reports
  - Security Settings
  - Teams
  - Webhooks
- name: Business tools
  tags:
  - AI Classifications
  - Assignment Settings
  - Calls
  - AI Phone Lines
  - Connectors
  - ElevenLabs Integration
  - Facebook Marketing
  - HellouAI Integration
  - Knowledge Base
  - Marketing Consent
  - Plan Upgrades
  - Voice Campaigns
  - WhatsApp Campaigns
  - WhatsApp Flows
  - WhatsApp Templates
- name: Client
  tags:
  - Inbox API
  - Contacts API
  - Conversations API
  - Messages API
- name: Others
  tags:
  - CSAT Survey Page