Hi @shov , this behavior is confusing but unfortunately pretty consistent once you know where the sanitization happens.
The key thing to know is that HubSpot rich text properties are HTML-first, but they still go through a server-side sanitizer that behaves slightly differently depending on how the request is constructed. Newlines (\n) are not a reliable formatting mechanism here.
The safest approach is to always send explicit HTML, especially <br> or <p> tags, rather than relying on escaped control characters. In practice, <br> is much more predictable than \n. The difference you’re seeing between your integration and the API Playground usually comes down to double escaping and middleware behavior.
The Playground sends a raw JSON body exactly as written, while many HTTP clients or frameworks will automatically escape strings, normalize newlines, or sanitize HTML before the request ever reaches HubSpot. That’s why you may see <a> tags preserved in the Playground but stripped when sent via your integration.
Another important nuance is that HubSpot strips certain tags or attributes if they don’t meet its allowlist. <a> is allowed, but attributes like target, rel, inline styles, or malformed URLs can cause the entire tag to be dropped. Always send fully qualified URLs and keep anchor tags very simple. This behavior is documented indirectly in the CRM properties API expectations (https://developers.hubspot.com/docs/api-reference/crm-properties-v3/guide )
So the practical rules of thumb are:
Send clean HTML, not escaped text.
Replace \n with <br> or wrap content in <p> tags.
Inspect the exact payload after your client library serializes it.
Avoid client-side sanitizers unless you explicitly control them.
If you can log the final JSON body right before the request is sent, that usually makes the root cause obvious very quickly.
Did my answer help? Please mark it as a solution to help others find it too.
Ruben Burdin HubSpot Advisor Founder @ Stacksync Real-Time Data Sync between any CRM and Database
Hi @shov , this behavior is confusing but unfortunately pretty consistent once you know where the sanitization happens.
The key thing to know is that HubSpot rich text properties are HTML-first, but they still go through a server-side sanitizer that behaves slightly differently depending on how the request is constructed. Newlines (\n) are not a reliable formatting mechanism here.
The safest approach is to always send explicit HTML, especially <br> or <p> tags, rather than relying on escaped control characters. In practice, <br> is much more predictable than \n. The difference you’re seeing between your integration and the API Playground usually comes down to double escaping and middleware behavior.
The Playground sends a raw JSON body exactly as written, while many HTTP clients or frameworks will automatically escape strings, normalize newlines, or sanitize HTML before the request ever reaches HubSpot. That’s why you may see <a> tags preserved in the Playground but stripped when sent via your integration.
Another important nuance is that HubSpot strips certain tags or attributes if they don’t meet its allowlist. <a> is allowed, but attributes like target, rel, inline styles, or malformed URLs can cause the entire tag to be dropped. Always send fully qualified URLs and keep anchor tags very simple. This behavior is documented indirectly in the CRM properties API expectations (https://developers.hubspot.com/docs/api-reference/crm-properties-v3/guide )
So the practical rules of thumb are:
Send clean HTML, not escaped text.
Replace \n with <br> or wrap content in <p> tags.
Inspect the exact payload after your client library serializes it.
Avoid client-side sanitizers unless you explicitly control them.
If you can log the final JSON body right before the request is sent, that usually makes the root cause obvious very quickly.
Did my answer help? Please mark it as a solution to help others find it too.
Ruben Burdin HubSpot Advisor Founder @ Stacksync Real-Time Data Sync between any CRM and Database
I'm tagging @DanielPicklo and @Mike_Eastwood to see if they have insights into this specific behavior, as they often work with custom API integrations.
Because this is a rich text field, the API typically expects HTML formatting rather than relying on raw newline control characters. Try replacing your \n characters with <br> tags in your integration’s payload. This often resolves issues where line breaks are either ignored or displayed incorrectly.
Since the <a> tags work in the API Playground (which sends a raw JSON body) but are stripped or altered in your integration, also take a close look at the HTTP client, framework, or middleware you’re using. Some libraries automatically sanitize or escape HTML to prevent XSS attacks, which can result in tags being removed or turned into text.
Could you share a sanitized snippet of the exact JSON body your integration is sending (including headers if possible)? Seeing the real structure will make it easier to tell whether the HTML is being stripped, escaped, or malformed.