Skip to content

Create a channel in a workspace

POST
/api/workspaces/{workspaceId}/channels

Creates a channel in a workspace. An email channel is provisioned after the call returns and moves through the pending statuses of its inbound_mode to active; an inbox_api channel waits in draft until its mailbox is connected in the dashboard. A chat channel is active at once. A voice channel is active at once when its phone number is, and pending_activation while the number is in review with the carrier. For voice channels, bind a provisioned phone number via phoneNumberId. The created channel record is returned; an email channel’s record carries what the mode needs set up outside oHallo: config.inbound_address where oHallo generates it, and config.dns_records where the mode has records to publish.

workspaceId
required
string format: uuid

The unique identifier of the workspace to create the channel in.

object
channelType
required

The type of channel to create.

string
Allowed values: email chat whatsapp voice_phone
Example
email
displayName
required

A human-readable name for the channel. Leading and trailing whitespace is trimmed.

string
>= 1 characters
Example
Support Email
config

Channel-specific configuration, validated against the shape for channelType: the email channel config for email, the chat channel config for chat and the voice channel config for voice_phone. An email channel needs one; the other types accept an empty object, the default.

object
Any of:
Email channel config

The configuration of an email channel. inbound_mode decides how mail reaches oHallo and which fields the channel needs. A config without inbound_mode is read as subdomain, with inbound_address taken from from_address. While it provisions the channel, oHallo adds keys of its own, marked read-only: the inbound_address it generates, the DNS records to publish, and error_message when provisioning fails. A channel is created in subdomain, forwarding, inbox_api or mail_routing_rule; another inbound_mode on create, or a new mode on update other than subdomain, forwarding or inbox_api, answers 422.

object
One of:
subdomain

A subdomain given to oHallo, for example help.example.com, receives the mail itself. Publish the records in dns_records on it. The channel turns active once the domain is verified. The addresses are on a subdomain of a registrable domain, as the Public Suffix List draws it: an address on a registrable domain itself, such as support@example.com or support@example.co.uk, answers 422 with the message on that address, since an MX record there would receive all of the domain’s mail.

object
inbound_mode

subdomain, which is also how a config without inbound_mode is read.

string
Allowed values: subdomain
from_address
required

The address customers write to and replies come from: an address on the subdomain.

string format: email
Example
support@help.example.com
inbound_address

The address mail is received at, the same as from_address. Required when inbound_mode is sent; without inbound_mode it is taken from from_address.

string format: email
Example
support@help.example.com
domain

The domain the DNS records belong to, written by oHallo.

string
Example
help.example.com
dns_records

The DNS records an email channel needs, written by oHallo. Publish each at the DNS host of its domain. The verification record, the DKIM records and the MX record route and verify mail; SPF and DMARC serve the delivery of replies.

object
verification_txt

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
dkim_cnames
Array<object>

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
mx

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
spf

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
dmarc

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
domain

On a mail_routing_rule channel, the domain the DKIM records belong to.

string
error_message

Why provisioning failed, when the channel’s status is error and the reason is known.

string
Example
{
"inbound_mode": "subdomain",
"from_address": "support@help.example.com",
"inbound_address": "support@help.example.com"
}
enabled

Whether the channel is enabled. Defaults to true.

boolean
Example
true
welcomeGreetingAttested

EU AI Act Article 50 confirmation for a greeting override in config.welcome_greeting on a voice channel: the same rule as attested on a workspace greeting (voiceGreetings). A new or changed override is refused with 422 and code greeting_attestation_required unless this is true, and refused with code greeting_must_mention_ai when the wording does not mention the assistant. An override without a valid confirmation is replaced at call time by the standard opening line.

boolean
Example
true
phoneNumberId

The provisioned phone number to bind. Required when the channel type is voice_phone, and not permitted for other types.

string format: uuid

The channel was created.

A channel represents a communication pathway through which oHallo sends and receives messages. Each channel has a type, configuration, and provisioning status.

object
id
required

Unique identifier for the channel.

string format: uuid
Example
d4e5f6a7-b8c9-0123-4567-890abcdef012
workspaceId
required

Workspace the channel belongs to.

string format: uuid
Example
a1b2c3d4-e5f6-7890-abcd-ef1234567890
tenantId
required

The account the channel belongs to.

string format: uuid
Example
a0b1c2d3-4567-89ab-cdef-0123456789ab
brandId

On a read by id: the brand the channel answers for, which is the brand of its workspace.

string | null format: uuid
channelType
required

Channel type: email, chat, whatsapp or voice_phone. The type decides the shape of config.

string
Example
email
displayName
required

Human-readable name.

string
Example
Support Email
status
required

Where the channel stands. draft: set up but not live; an inbox_api email channel stays in draft until its mailbox is connected in the dashboard. pending_dns: a subdomain, subdomain_with_redirect or mail_routing_rule email channel waits for its DNS records to be published and to resolve; a mail_routing_rule channel waits here until its DKIM records are verified, for up to 72 hours, after which it moves to error. pending_verification: the channel’s DNS records resolve, and oHallo is completing the verification of its domain. pending_setup: a mail_routing_rule or subdomain_with_redirect email channel waits for the first message its mail-flow rule redirects, and turns active when it arrives. pending_inbound: a forwarding email channel waits for the first forwarded message, and turns active when it arrives. pending_activation: a voice channel waits while its phone number is in review with the carrier, and turns active when the number is approved. active: the channel receives and sends messages; a successful connectivity test also sets it, on every channel but a mail_routing_rule one. error: provisioning failed, a connectivity test failed on an active channel, or a connected mailbox needs to be connected again; after a provisioning failure config.error_message says why when the reason is known. The retry endpoint provisions an email channel again, and a connected mailbox is connected again in the dashboard. inactive: a connected mailbox was disconnected, and the channel receives and sends nothing until the mailbox is connected again. deprovisioned: the channel was deleted; channel lists leave it out, and a read by id returns it.

string
Allowed values: draft pending_dns pending_verification pending_setup pending_inbound pending_activation active error inactive deprovisioned
Example
active
enabled
required

Whether the channel is enabled.

boolean
Example
true
provisioningWorkflowId

The id of the run that provisions an email channel; null on a channel no provisioning run was started for, such as a chat, voice or inbox_api channel.

string | null
lastVerifiedAt

When a connectivity test, or the disconnection of a mailbox, last set the channel’s status; null before either.

string | null format: date-time
config
required

The channel’s configuration, in the shape for its channelType: the email channel config for email, the chat channel config for chat and the voice channel config for voice_phone. It holds settings only; channel credentials are stored apart and never returned.

object
Any of:
Email channel config

The configuration of an email channel. inbound_mode decides how mail reaches oHallo and which fields the channel needs. A config without inbound_mode is read as subdomain, with inbound_address taken from from_address. While it provisions the channel, oHallo adds keys of its own, marked read-only: the inbound_address it generates, the DNS records to publish, and error_message when provisioning fails. A channel is created in subdomain, forwarding, inbox_api or mail_routing_rule; another inbound_mode on create, or a new mode on update other than subdomain, forwarding or inbox_api, answers 422.

object
One of:
subdomain

A subdomain given to oHallo, for example help.example.com, receives the mail itself. Publish the records in dns_records on it. The channel turns active once the domain is verified. The addresses are on a subdomain of a registrable domain, as the Public Suffix List draws it: an address on a registrable domain itself, such as support@example.com or support@example.co.uk, answers 422 with the message on that address, since an MX record there would receive all of the domain’s mail.

object
inbound_mode

subdomain, which is also how a config without inbound_mode is read.

string
Allowed values: subdomain
from_address
required

The address customers write to and replies come from: an address on the subdomain.

string format: email
Example
support@help.example.com
inbound_address

The address mail is received at, the same as from_address. Required when inbound_mode is sent; without inbound_mode it is taken from from_address.

string format: email
Example
support@help.example.com
domain

The domain the DNS records belong to, written by oHallo.

string
Example
help.example.com
dns_records

The DNS records an email channel needs, written by oHallo. Publish each at the DNS host of its domain. The verification record, the DKIM records and the MX record route and verify mail; SPF and DMARC serve the delivery of replies.

object
verification_txt

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
dkim_cnames
Array<object>

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
mx

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
spf

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
dmarc

One DNS record to publish.

object
type
required

The record type.

string
Allowed values: TXT CNAME MX
name
required

The record’s name.

string
value
required

The record’s value.

string
priority

The priority of an MX record.

integer
domain

On a mail_routing_rule channel, the domain the DKIM records belong to.

string
error_message

Why provisioning failed, when the channel’s status is error and the reason is known.

string
Example
{
"inbound_mode": "subdomain",
"from_address": "support@help.example.com",
"inbound_address": "support@help.example.com",
"domain": "help.example.com"
}
publicKey

A chat channel’s public key: the data-key of the code that puts the chat on a website. null on the other channel types.

string | null
phoneNumberId

The phone number a voice channel answers; null on the other channel types.

string | null format: uuid
credentialsRef

The reference oHallo uses to read the channel’s stored credentials at runtime, never the credentials themselves; null when none are stored.

string | null
languageOverride

Has no effect.

array | null
publishedVersionId

The channel’s current configuration version.

string | null format: uuid
createdAt
required

Timestamp when the channel was created.

string format: date-time
Example
2026-01-10T08:00:00.000Z
updatedAt
required

Timestamp when the channel was last updated.

string format: date-time
Example
2026-01-10T08:00:00.000Z
welcomeGreetingAttestation

EU AI Act Article 50 confirmation covering the exact greeting override in config.welcome_greeting on a voice channel, composed by the server when the override is saved with welcomeGreetingAttested.

object
attestedByUserId
string
attestedAt
string format: date-time
greetingHash
string
language

The language the override was confirmed in. The confirmation covers the override only while the line’s language (config.language, else the workspace’s operating language) is this language.

string
Example
da
welcomeGreetingAttestationValid

Whether the stored confirmation still covers the override in config.welcome_greeting, in the line’s language. False means callers hear the standard opening line on this number until the override is confirmed again.

boolean

The caller may not create a channel here. People need the owner or admin role. An API key needs the channels:write scope; a workspace outside the key’s brand or workspace restriction answers 404.

Standard error response returned by all endpoints on failure.

object
error
required

A human-readable error message describing what went wrong.

string
Example
Conversation not found
code

A machine-readable reason on some refusals, for example ‘key_lock’ when an API key’s brand or workspace restriction does not cover the action.

string
Example
key_lock
missing_scopes

On a 403 for an API key without a scope the endpoint requires: the scopes the key lacks.

Array<string>
Example
[
"mcp:write"
]
entryId

On a 409 with code duplicate_question or duplicate_rule_text: the knowledge base entry or policy that already holds the question or rule text.

string format: uuid
Example
11223344-5566-4788-99aa-bbccddeeff00
connectionId

On a 422 about one MCP connection a request names, from an assignment or an agent create or update (a connection that does not exist, one listed twice, or one that does not declare a tool named): the connection, as the request named it.

string
undeclaredTools

On the same 422: the tool names the connection does not declare.

Array<string>
Example
[
"get_orders"
]
declaredTools

On the same 422: the tools the connection declares.

Array<string>
Example
[
"get_order",
"search_orders"
]

The requested phone number is already bound to another voice channel, or the account’s billing is suspended or closed, which stops new chat and voice channels (error: billing_restricted).

Standard error response returned by all endpoints on failure.

object
error
required

A human-readable error message describing what went wrong.

string
Example
Conversation not found
code

A machine-readable reason on some refusals, for example ‘key_lock’ when an API key’s brand or workspace restriction does not cover the action.

string
Example
key_lock
missing_scopes

On a 403 for an API key without a scope the endpoint requires: the scopes the key lacks.

Array<string>
Example
[
"mcp:write"
]
entryId

On a 409 with code duplicate_question or duplicate_rule_text: the knowledge base entry or policy that already holds the question or rule text.

string format: uuid
Example
11223344-5566-4788-99aa-bbccddeeff00
connectionId

On a 422 about one MCP connection a request names, from an assignment or an agent create or update (a connection that does not exist, one listed twice, or one that does not declare a tool named): the connection, as the request named it.

string
undeclaredTools

On the same 422: the tool names the connection does not declare.

Array<string>
Example
[
"get_orders"
]
declaredTools

On the same 422: the tools the connection declares.

Array<string>
Example
[
"get_order",
"search_orders"
]

Validation error. One or more required fields are missing or invalid, an email channel’s inbound_mode is not subdomain, forwarding, inbox_api or mail_routing_rule, or a subdomain channel’s from_address or inbound_address is on a registrable domain itself, such as support@example.com or support@example.co.uk, rather than on a subdomain of one. A config field’s message is under details.fieldErrors.config, prefixed with the field’s name.

Standard error response returned by all endpoints on failure.

object
error
required

A human-readable error message describing what went wrong.

string
Example
Conversation not found
code

A machine-readable reason on some refusals, for example ‘key_lock’ when an API key’s brand or workspace restriction does not cover the action.

string
Example
key_lock
missing_scopes

On a 403 for an API key without a scope the endpoint requires: the scopes the key lacks.

Array<string>
Example
[
"mcp:write"
]
entryId

On a 409 with code duplicate_question or duplicate_rule_text: the knowledge base entry or policy that already holds the question or rule text.

string format: uuid
Example
11223344-5566-4788-99aa-bbccddeeff00
connectionId

On a 422 about one MCP connection a request names, from an assignment or an agent create or update (a connection that does not exist, one listed twice, or one that does not declare a tool named): the connection, as the request named it.

string
undeclaredTools

On the same 422: the tool names the connection does not declare.

Array<string>
Example
[
"get_orders"
]
declaredTools

On the same 422: the tools the connection declares.

Array<string>
Example
[
"get_order",
"search_orders"
]