Markup
Apply rich formatting to message text using structured markup objects.
Previous syntax deprecated. The old markdown-style markup syntax (e.g. bold, ##Header) is no longer supported. All formatting must now use the structured markup object format described below.
Overview
Markups let you annotate a range of characters within a message's text field. Instead of inline syntax, you pass one or more markups form fields alongside your text, each describing a formatting rule by its character range and type.
Multiple markups can be applied to the same message, and their ranges can overlap. Each markup is an independent JSON object.
Markup Structure
Every markup object shares these base keys:
| Key | Type | Required | Description |
|---|---|---|---|
| type | String | required | One of the MarkupTypes enum values (see below) |
| start | Number | required | Zero-based character index where the markup begins (inclusive) |
| end | Number | required | Zero-based character index where the markup ends (inclusive) |
| visibleText | String | optional | Override text shown to the recipient. |
Type-specific keys are added on top of these base keys depending on the type value.
Sending Markups
Markups are sent as repeated multipart/form-data fields. Each markup is a separately JSON-encoded markups field alongside the text field.
cURL example — multiple markups on one message
curl --request POST \
--url 'https://api.yophone.com/v1/messages' \
--form 'text="Hello"' \
--form 'markups="{\"type\":\"bold\",\"start\":0,\"end\":4}"' \
--form 'markups="{\"type\":\"link\",\"start\":11,\"end\":14,\"visibleText\":\"a\",\"url\":\"https://example.com\"}"'
Each markups value must be a valid JSON-encoded string. When sending via an SDK or HTTP library, serialize the object to JSON first, then pass it as the field value.
Markup Types
The type field accepts one of the following MarkupTypes enum values:
Type-Specific Keys
Certain types require additional keys in the markup object:
| Key | Type | Required | Description |
|---|---|---|---|
| link | url required | string | The URL to navigate to when the text is tapped. E.g. "https://fb.com" |
| mention | userUid required | string | The UID of the user being mentioned. E.g. "uid_abc123" |
| color | color required | string | A hex color string applied to the text foreground. E.g. "#9D0D54" |
Full Example
The following cURL request demonstrates every markup type in a single message. The text field contains the raw string; each --form 'markups=...' line applies a formatting rule to a character range within it.
Message text (for reference)
"Heading1\n\nHeading2\n\n@Mention built COLOR with support of:\n • BOLD,\n • ITALIC,\n • UNDERLINE,\n • STRIKE and\n • MIX.\n\nYou can copy COPIABLE and call NUMBER.\n\nVisit LINK for more info or contact @MENTION."
cURL
curl --request POST \
--url 'https://api.yophone.com/v1/messages' \
--header 'X-YoAI-API-Key: <YOUR_API_KEY>' \
--form 'to="<RECIPIENT_UID>"' \
--form 'text="Heading1\n\nHeading2\n\n@Mention built COLOR with support of:\n • BOLD,\n • ITALIC,\n • UNDERLINE,\n • STRIKE and\n • MIX.\n\nYou can copy COPIABLE and call NUMBER.\n\nVisit LINK for more info or contact @MENTION."' \
# heading1 applied to "Heading1" (chars 0–8)
--form 'markups="{\"type\":\"heading1\",\"start\":0,\"end\":8,\"visibleText\":\"Editor Demo\"}"' \
# heading2 applied to "Heading2" (chars 10–18)
--form 'markups="{\"type\":\"heading2\",\"start\":10,\"end\":18,\"visibleText\":\"Formatting Example\"}"' \
# mention — @Mention (chars 20–28), userUid identifies the tagged user
--form 'markups="{\"type\":\"mention\",\"start\":20,\"end\":28,\"visibleText\":\"\",\"url\":\"\",\"userUid\":\"<USER_UID>\"}"' \
# color + bold stacked on same range "COLOR" (chars 35–40)
--form 'markups="{\"type\":\"color\",\"start\":35,\"end\":40,\"visibleText\":\"this editor\",\"color\":\"#9D0D54\"}"' \
--form 'markups="{\"type\":\"bold\",\"start\":35,\"end\":40,\"visibleText\":\"this editor\"}"' \
# individual style demos
--form 'markups="{\"type\":\"bold\",\"start\":61,\"end\":65,\"visibleText\":\"Bold\"}"' \
--form 'markups="{\"type\":\"italic\",\"start\":70,\"end\":76,\"visibleText\":\"Italic\"}"' \
--form 'markups="{\"type\":\"underline\",\"start\":81,\"end\":90,\"visibleText\":\"Underline\"}"' \
--form 'markups="{\"type\":\"strike\",\"start\":95,\"end\":101,\"visibleText\":\"Strike\"}"' \
# MIX (chars 109–112) — multiple types stacked on the same range
--form 'markups="{\"type\":\"bold\",\"start\":109,\"end\":112,\"visibleText\":\"Mix\"}"' \
--form 'markups="{\"type\":\"italic\",\"start\":109,\"end\":112,\"visibleText\":\"Mix\"}"' \
--form 'markups="{\"type\":\"strike\",\"start\":109,\"end\":112,\"visibleText\":\"Mix\"}"' \
--form 'markups="{\"type\":\"color\",\"start\":109,\"end\":112,\"visibleText\":\"Mix\",\"color\":\"#7A3FE0\"}"' \
--form 'markups="{\"type\":\"heading1\",\"start\":109,\"end\":112,\"visibleText\":\"Mix\"}"' \
# copy — tapping copies "123456" to clipboard (chars 128–136)
--form 'markups="{\"type\":\"copy\",\"start\":128,\"end\":136,\"visibleText\":\"123456\"}"' \
# phoneNumber — tapping opens dialer (chars 146–152)
--form 'markups="{\"type\":\"phoneNumber\",\"start\":146,\"end\":152,\"visibleText\":\"+37499123456\"}"' \
# link — tapping opens URL (chars 161–165)
--form 'markups="{\"type\":\"link\",\"start\":161,\"end\":165,\"visibleText\":\"DOCS\",\"url\":\"https://yoai.yophone.com/docs/markup\"}"' \
# second mention — @MENTION (chars 191–199)
--form 'markups="{\"type\":\"mention\",\"start\":191,\"end\":199,\"visibleText\":\"\",\"url\":\"\",\"userUid\":\"<USER_UID_2>\"}"'
Multiple markups can target the same character range — as shown with MIX above, where bold, italic, strike, color, and heading1 are all applied to chars 109–112 simultaneously.