Preserving article editor formatting when updating help center articles using the API
If your content creation workflow includes updating articles with both the help center article editor and the Help Center API, then you might encounter some formatting issues.
You can skip this article if you use either of the following workflows:
-
Your content contributors only update articles with the article editor.
-
Your contributors update source files in a separate content management system and only update the articles in the help center with the Help Center API (usually through some app or integration). In this workflow in fact, your content contributors should avoid using the article editor completely to prevent their changes from being overwritten by updates to the source files.
However, if your contributors update articles with the article editor and you use the API to download articles from the help center from time to time to make some bulk updates to them offline before putting them back, you might experience the issues discussed in this article.
The help center’s article editor may change some underlying HTML structures in an API-source article when the article is opened and saved in the editor UI, especially for code blocks, to match the structure it uses internally.
If you later update articles using the Help Center API, you can accidentally reintroduce legacy HTML or remove editor-aligned HTML patterns like code block classes and nested elements. This can lead to formatting differences when the article is rendered in the editor.
If you have this blended content workflow, this article provides recommendations for workflows that GET the current article body from Help Center, apply targeted changes (such as bulk find and replace), and PUT the updated body back.
Limitations
-
The current Help Center API accepts and stores article bodies as HTML, but it does not fully support the editor’s content model. Editor-only structures, such as HTML block or content block wrappers, may not be preserved when content is retrieved and updated using the API. As a result, the HTML returned by the API may differ from what you see in the editor. See HTML blocks and the Help Center API. For content blocks, see Help Center API limitations with content blocks. Workflows that mix UI edits and API edits may require additional review and testing.
-
If you update an article with the Help Center API, the Knowledge UI will treat it as API-updated and may show it as not migrated. Opening such an article in the editor may require an explicit action, such as saving or migrating, before you can edit it in the UI.
-
When an article is opened in the editor, the editor may convert certain legacy HTML patterns into the structure it uses internally (for example, rewriting plain
<pre>code blocks into the editor-aligned structure). If the editor shows Save and migrate, the article may not be fully migrated yet. Until migration is complete, the HTML returned by the API may not reflect the editor-aligned structure. After you save and migrate, code blocks are more likely to appear as<pre class="wysiwyg-code-block"><code ...>...</code></pre>.
Best practices for updates
To reduce formatting changes and unexpected migrations:
-
Keep article body HTML clean and semantic. Use structural elements (headings, paragraphs, lists, links, and editor-aligned code blocks) and move styling and scripting to your help center theme (CSS or JS) whenever possible.
-
GET the latest article immediately before updating. Don’t PUT a cached body after someone edited the article in the UI.
-
Perform small changes, such as replacing a specific string, rather than regenerating the entire HTML body.
-
Avoid HTML cleanup that changes structure. Be careful with HTML sanitizers, prettifiers, DOM reserialization, and template engines that:
- remove
classattributes - rewrite whitespace or tag nesting
- normalize void tags
- drop elements or attributes
- remove
-
Preserve editor-based HTML patterns. If you see class names or nested markup that you didn’t create, such as within code blocks, do not remove them unless you are intentionally changing formatting.
-
For bulk edits, such as find and replace, use simple string replacements instead of parsing and rewriting the entire HTML body.
-
If your workflow maintains article content in an external “source of truth” (for example, source files in version control), avoid mixing editor-based edits with API-based updates. Any UI edits can be overwritten by a later API update. If you must support both, ensure the external source uses editor-aligned HTML patterns (especially code blocks) and always base updates on a fresh GET.
-
Adopt the editor’s preferred HTML structures, especially for code blocks. See Code blocks.
Example: Updating an article body
Always retrieve the latest version of the article immediately before updating it. This helps prevent overwriting editor-aligned HTML with an older cached version.
-
GET the article.
curl
curl -sS \-u "{email_address}/token:{api_token}" \-H "Content-Type: application/json" \"https://{subdomain}.zendesk.com/api/v2/help_center/articles/{article_id}.json"Python
import requestsZENDESK_SUBDOMAIN = "your_subdomain"ARTICLE_ID = 123456789ZENDESK_USER_EMAIL = "[email protected]"ZENDESK_API_TOKEN = "your_api_token"AUTH = (f"{ZENDESK_USER_EMAIL}/token", ZENDESK_API_TOKEN)url = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/help_center/articles/{ARTICLE_ID}.json"resp = requests.get(url, auth=AUTH, headers={"Content-Type": "application/json"})resp.raise_for_status()article = resp.json()["article"]body = article.get("body")Depending on your locale workflow, you may need to use translation endpoints to read and write the article body.
-
Modify only what you need. Make minimal changes and preserve existing classes and nested elements in the HTML.
-
PUT the updated body.
curl
curl -sS -X PUT \-u "{email_address}/token:{api_token}" \-H "Content-Type: application/json" \"https://{subdomain}.zendesk.com/api/v2/help_center/articles/{article_id}.json" \-d '{"article": {"body": "<h2>Example</h2><p>Updated using the API.</p>"}}'Python
import requestsZENDESK_SUBDOMAIN = "your_subdomain"ARTICLE_ID = 123456789ZENDESK_USER_EMAIL = "[email protected]"ZENDESK_API_TOKEN = "your_api_token"AUTH = (f"{ZENDESK_USER_EMAIL}/token", ZENDESK_API_TOKEN)url = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/help_center/articles/{ARTICLE_ID}.json"updated_body = "<h2>Example</h2><p>Updated using the API.</p>"payload = {"article": {"body": updated_body}}resp = requests.put(url, auth=AUTH, headers={"Content-Type": "application/json"}, json=payload)resp.raise_for_status()print("Updated article:", resp.json()["article"]["id"])
Code blocks
Code blocks are the most common source of unexpected formatting changes when alternating between editor updates and API updates. They’re especially sensitive because the editor standardizes code blocks to a single HTML structure that themes and syntax highlighting typically rely on.
If your integration stores article HTML outside Zendesk, update that stored HTML to the editor-aligned code block structure so future API updates don’t reintroduce legacy <pre> blocks.
How the editor migrates legacy code blocks
When a legacy code block is opened in the editor, the editor may migrate it into the structure it uses internally. For example, a plain <pre> may be converted into <pre class="wysiwyg-code-block"><code …>…</code></pre>.
Example
Legacy HTML:
<pre>console.log("Hello")</pre>
After opening and saving in the editor:
<preclass="wysiwyg-code-block"><code class="language-javascript">console.log("Hello")</code></pre>
If your integration generates code blocks, use the editor-aligned structure (don’t send <pre>…</pre> by itself):
<preclass="wysiwyg-code-block"><code class="language-javascript">console.log("Hello")</code></pre>
HTML blocks and the Help Center API
Some users try to keep sections of HTML unchanged by wrapping them inside an HTML block in the editor UI. This approach does not work reliably with the Help Center API because HTML block wrapper elements aren’t preserved across API GET and PUT requests:
- When you GET an article using the API, the response may include only the inner HTML, without the HTML block wrapper elements.
- When you PUT an update using the API, Zendesk saves exactly the HTML you send (including the absence of those wrappers).
- When the article is opened again in the editor, the editor may re-migrate the HTML and re-wrap unsupported sections in HTML blocks.
As a result, even small API changes (such as adding a period) can remove HTML block wrappers because the API does not preserve those wrapper elements when you retrieve and update the article body.
If you must regularly update an article with the API and also edit it in the UI, use editor-compatible HTML patterns rather than relying on HTML block wrappers being preserved when retrieving and updating articles using the current API.
Troubleshooting
Code blocks lose styling after an API update
Symptoms
- Code blocks render as plain preformatted text
- Syntax highlighting or styling changes unexpectedly
- Code-block markup changes after switching between API edits and editor edits
Likely causes
- Your PUT payload contained legacy
<pre>...</pre>blocks - Your tooling stripped
class="wysiwyg-code-block"or removed the nested<code> - An HTML sanitizer or formatter rewrote the structure
Fix
Update code blocks to the editor-aligned structure described in Code blocks, and ensure your integration preserves the <pre class="wysiwyg-code-block"><code ...>...</code></pre> structure on future updates.
API updates cause larger formatting differences later in the editor
Likely causes
- Your integration overwrote newer editor-normalized HTML with stale or cached content
- Your integration rewrote the full HTML body
Fix
- Always GET immediately before PUT
- Apply minimal changes and preserve classes and nesting