API Reference

Messages

Send contact (vCard) message

Sends a contact card. message.contacts must be a non-empty array and every card requires a non-empty name; phones[].number, emails[].address, organization, and title are optional. WhatsApp-only for now; invalid contact content returns 400 invalid_request, and non-WhatsApp providers return 400 unsupported_message_type.

POSThttps://api.unifyport.ai/v1/messages

Before you call

Use a server-side X-Api-Key for the workspace that owns the resource. Replace every placeholder before running a sample.

Complete the selected authorization flow and check runtime_status. Authorization and connection state are separate; HTTP success alone does not establish readiness.

Prepare your parameters
account_id
Use data.id from account creation or an account query. Account identifiers belong to the workspace selected by X-Api-Key. Get account
to.id · to.type
For a reply, copy data.conversation.id and data.conversation.type from message.received into to.id and to.type. For a new recipient, follow the channel-specific identifier rules. Unified message sending support

Request parameters

Headers

X-Api-Key
stringrequired

Workspace API key. The workspace is resolved from this header.

Content-Type
stringrequired

Use application/json when sending a JSON request body.

Request body

provider_data
object

Provider-specific send options, effective only for supported providers and message types. WhatsApp audio/video seconds is a non-negative integer. For video only, use 0 to 4294967295; waveform is audio-only. Use top-level reply_to for quoted replies where supported. For sticker, omit provider_data or use an empty object; a non-object returns 400 invalid_request and a non-empty object returns 400 provider_invalid_request.

seconds
integer

Optional non-negative integer duration in seconds for WhatsApp audio and video messages. For video only, the allowed range is 0 to 4294967295.

minimum: 0

waveform
string

Optional waveform data for WhatsApp audio messages. Non-empty values must use standard Base64 encoding and decode to parseable JSON waveform data; an empty string is treated as omitted, and invalid formats return HTTP 400 provider_invalid_request.

account_id
stringrequired

Provider account that sends the message.

minLength: 1

to
objectrequired

Recipient target with id and type.

id
stringrequired

Channel-side recipient identifier.

minLength: 1

type
stringrequired

Standard conversation type: user, group, or channel. WhatsApp community announcement groups continue to use group.

enum: user, group, channel

message
objectrequired

Normalized message payload. Text uses message.text; media uses message.url.

type
stringrequired

Message type: text, image, video, audio, document, file, contact, link_preview, poll, or sticker.

enum: text, image, video, audio, document, file, contact, link_preview, poll, sticker

text
string

Non-empty body required for text and link_preview. For link_preview it must contain a non-whitespace character; WhatsApp also requires the exact link_preview.url in the body.

minLength: 1

caption
string

Optional caption for image, video, document, or file messages.

url
string

Non-empty absolute HTTP(S) media URL. Media messages require url, file_url, or file_key.

format: uri · pattern: ^[Hh][Tt][Tt][Pp][Ss]?://

file_url
string

Non-empty alternative absolute HTTP(S) media URL. Media messages require url, file_url, or file_key.

format: uri · pattern: ^[Hh][Tt][Tt][Pp][Ss]?://

file_key
string

Non-empty provider or storage file reference. Media messages require url, file_url, or file_key.

contacts[]
object[]

Non-empty array of structured contact cards required when message.type is contact.

minItems: 1

name
string

Non-empty contact display name required for every contact card.

minLength: 1

phones[]
object[]

Phone entries included in the contact card.

number
string

Phone number; required for every phone entry.

type
string

Optional phone label such as CELL or WORK.

emails[]
object[]

Email entries included in the contact card.

address
string

Email address; required for every email entry.

format: email

type
string

Optional email label such as WORK or HOME.

organization
string

Optional organization associated with the contact.

title
string

Optional job title associated with the contact.

link_preview
object

Required only for message.type=link_preview, together with text; cannot be mixed with other payloads. The public structure requires only url; optional title and description allow empty strings, not null. WhatsApp requires non-empty title/image_url and limits title to 255 and description to 1024 Unicode characters under this API send policy.

url
string

Required target link: an absolute HTTP(S) URI with a hostname and no whitespace; bracketed addresses must be IPv6 literals. Preserved verbatim; resource accessibility is not guaranteed.

pattern: ^[Hh][Tt][Tt][Pp][Ss]?://(?:[^/?#@\s]*@)?(?:\[[0-9A-Fa-f:.]+\]|[^/?#:@\s\[\]]+)(?::[0-9]*)?(?:[/?#]|$)

title
string

Optional preview title; empty string allowed, null forbidden. WhatsApp requires a non-empty title of at most 255 Unicode characters.

description
string

Optional preview summary; empty string allowed, null forbidden. WhatsApp allows at most 1024 Unicode characters.

image_url
string

Optional image URI, required and non-empty for WhatsApp. Must be an absolute HTTP(S) URI with a hostname and no whitespace; bracketed addresses must be IPv6 literals. Preserved verbatim; resource accessibility is not guaranteed.

pattern: ^[Hh][Tt][Tt][Pp][Ss]?://(?:[^/?#@\s]*@)?(?:\[[0-9A-Fa-f:.]+\]|[^/?#:@\s\[\]]+)(?::[0-9]*)?(?:[/?#]|$)

poll
object

Required only for message.type=poll; cannot be mixed with text or other payloads. Requires question, options and max_selections. Question and option titles are preserved verbatim. The public structure sets no question length limit, maximum option count or duplicate-title restriction; providers may impose additional limits.

question
string

Required poll question containing a non-whitespace character; preserved verbatim.

minLength: 1 · pattern: \S

options[]
object[]

Required array of at least two options, each with a title.

minItems: 2

title
string

Required option title containing a non-whitespace character. Sent without trimming, case changes or Unicode normalization.

minLength: 1 · pattern: \S

max_selections
integer

Required maximum selections per voter, not the number of voters. Integer from 1 to the options count, validated by the API. Integer-valued numbers such as 1.0 and 1e0 equal 1; fractional values are invalid.

minimum: 1

reply_to
object

Quoted-reply target. Copy data.message.reply_token from the inbound webhook into reply_to.reply_token unchanged when supported.

reply_token
string

Opaque reply token copied unchanged from data.message.reply_token in the inbound webhook.

minLength: 1

mentions[]
object[]

Group-message @ target list. type=member uses the corresponding Provider member id; type=all mentions everyone only when the Provider supports it, otherwise unsupported_message_type is returned.

type
string

Mention target type. Omit it for member compatibility; type=member requires id, while type=all omits id and only applies to group chats.

enum: member, all

id
string

Provider member identifier required when type=member.

minLength: 1

Understand the result

Save message_id and provider_ref to correlate later events or troubleshoot. accepted is not a delivery receipt. Use receipt events only where the channel supports them; identifier formats vary by channel.

reply_token — Optional opaque WhatsApp reply handle returned after a successful send when the channel provides a referable message identifier. Pass it back unchanged; it is not a parent message id.

Response 200 OK

{
  "request_id": "<REQUEST_ID>",
  "data": {
    "message_id": "msg_example",
    "account_id": "acc_example",
    "status": "accepted",
    "provider_ref": "provider_msg_example",
    "reply_token": "<opaque WhatsApp reply handle>"
  }
}

Response body

message_id
string

UnifyPort message identifier (msg_...) for the accepted message.

account_id
string

Provider account this response refers to.

status
string

Acceptance status; accepted means the message was queued for delivery to the provider.

provider_ref
string

Provider-side message reference, once the provider assigns one.

reply_token
string

Optional opaque WhatsApp reply handle returned after a successful send when the channel provides a referable message identifier. Pass it back unchanged; it is not a parent message id.

Responses

200

200 OK

Request succeeded. See the example response body.

400

Bad Request

The request body, path, or parameters are invalid.

401

Unauthorized

The X-Api-Key header is missing or invalid.

409

Conflict

The requested operation conflicts with an existing provider account or resource.

500

Internal Server Error

The service encountered an unexpected error.

501

Not Implemented

The selected provider does not implement this operation.

502

Bad Gateway

The provider adapter or upstream provider could not complete the operation.

If the request fails

Inspect HTTP status and error.code/numeric_code, and keep request_id for diagnosis. Correct invalid parameters, complete required authorization or check runtime state as appropriate. Confirm the outcome before retrying a send or another write. Error reference

invalid_request · 10000 · 400
Check required fields, formats and channel conditions, then correct the request.
invalid_api_key · 11001 · 401
Check X-Api-Key and whether the workspace is active.
provider_not_ready · 30009 · 409
Check authorization and runtime. Restore the connection and confirm the previous result before retrying.
unsupported_message_type · 36000 · 400
Choose a supported operation or message type. Repeating the same request does not add channel support.
invalid_reply_token · 36006 · 400
Copy the inbound reply_token unchanged, not a message ID. Quoted replies require a supporting channel.