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: 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