# API: body vs body\_html

**URL:** <https://discourse.joplinapp.org/t/api-body-vs-body-html/11697>\
**Category:** Development\
**Created:** [14 October 2020 14:42 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697 "2020-10-14T14:42:30Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![msbentley](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/msbentley/32/1219_2.png) [@msbentley](https://discourse.joplinapp.org/u/msbentley)\
**Post date:** [14 October 2020 14:42 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/1 "2020-10-14T14:42:30Z")

</div>

Hi all,

I am writing a small script which queries the Evernote API and the Joplin API and uses these to resolve Evernote internal links (evernote://) in imported notes, and convert them to Joplin links (using the Evernote GUID + creation date to find the Joplin note correponding to the evernote:// link).

In doing so I ran across a couple of issues - firstly, could I clarify how `body` and `body_html` are used? Is the latter _only_ used by the web clipper? Should I expect either markdown _or_ html in the `body` element? Is there a way to distinguish which kind of note I retrieve? To know up front if I am dealing with an html or md note?

Also, when using the `/note/` endpoint with `body_html` as the field, I get a 500 server error.

Any clarification would be great! Once I've finished the code I'll push to GitHub and post to the #apps category.

Thanks! Mark

---

<div class="post-metadata">

**Author:** ![rxliuli](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/rxliuli/32/4083_2.png) [@rxliuli](https://discourse.joplinapp.org/u/rxliuli)\
**Post date:** [14 October 2020 15:45 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/2 "2020-10-14T15:45:19Z")

</div>

1. Body vs body\_html: Most of the time, when you want to manipulate note data, you should operate markdown instead of html. The latter is only automatically rendered by preview. I am not sure whether markdown will be automatically modified when body\_html is modified. This needs to be asked @laurent
2. If you encounter an error, please confirm what appears in the joplin console first, and display them to better locate the error. Refer to: [https://joplinapp.org/debugging/#desktop-application](https://joplinapp.org/debugging/#desktop-application).

> In addition, if possible, you can try to use the existing sdk instead of directly calling the original rest api, currently there is a nodejs/python version
> 
> - [joplin-api - npm](https://www.npmjs.com/package/joplin-api)
> - [https://pypi.org/project/joplin-api/](https://pypi.org/project/joplin-api/)

They should help you reduce some troubles (if you have relevant language knowledge)

---

<div class="post-metadata">

**Author:** ![msbentley](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/msbentley/32/1219_2.png) [@msbentley](https://discourse.joplinapp.org/u/msbentley)\
**Post date:** [14 October 2020 16:08 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/3 "2020-10-14T16:08:20Z")

</div>

Thanks @rxliuli - when importing Evernote .enex files, Joplin can either convert to markdown or keep the existing HTML, so I need to deal with links in both.

I think, from poking around, that I should always use the `body` field, and can check for an imported note by looking for the `<en-note>` tag at the start.

I did look at the python API package, but since my use case is very simple and I was trying to reduce the number of dependencies, I have so far simply use `requests` to handle it.

Thanks for the tip on debugging - if I have time I'll go back and see if there was any more info around the 500 error!

---

<div class="post-metadata">

**Author:** ![laurent](https://avatars.discourse-cdn.com/v4/letter/l/ce7236/32.png) [@laurent](https://discourse.joplinapp.org/u/laurent)\
**Post date:** [14 October 2020 16:10 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/4 "2020-10-14T16:10:24Z")

</div>

`body_html` indeed is only used by the clipper when **posting** a note. When you retrieve a note, you'll never get a body\_html field, it's more like a virtual field - to avoid having too much processing to do in the clipper, we send the whole HTML body to the app, which then converts it to Markdown. Once it's processed, the body\_html is discarded, which is why you can't get it back.

In the `body` element you should expect Markdown if markup\_language = 1, or HTML is markup\_language = 2. Of course keep in mind that Markdown notes may also contain HTML code, since HTML is valid inside Markdown. But HTML notes will only contain HTML.

> [@msbentley](#):
>
> Also, when using the `/note/` endpoint with `body_html` as the field, I get a 500 server error.

It's expected that it fails in this case, but in general when you get an error code you should inspect the response body, as it should contain more information. Actually could you check if you got any response body? If not, I'll take a look as that could be an error somewhere in the app.

---

<div class="post-metadata">

**Author:** ![msbentley](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/msbentley/32/1219_2.png) [@msbentley](https://discourse.joplinapp.org/u/msbentley)\
**Post date:** [14 October 2020 16:41 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/5 "2020-10-14T16:41:27Z")

</div>

Thanks @laurent - with that info I think I'm set - I see markdown\_language and it looks to be set correctly for my notes.

Re the error, indeed I was not correctly raising an exception when the API call worked, but the response was "bad" - for the 500 error before, the full response is:

```auto
'Internal Server Error: Error: SQLITE_ERROR: no such column: body_html: SELECT `body_html` FROM `notes` WHERE is_conflict = 0 ORDER BY `user_updated_time` DESC, `user_created_time` DESC, `title` DESC, `id` DESC: : \n\nError: Error: SQLITE_ERROR: no such column: body_html: SELECT `body_html` FROM `notes` WHERE is_conflict = 0 ORDER BY `user_updated_time` DESC, `user_created_time` DESC, `title` DESC, `id` DESC: \n at DatabaseDriverNode.sqliteErrorToJsError (/tmp/.mount_JoplinFq9O2U/resources/app.asar/lib/database-driver-node.js:21:18)\n at JoplinDatabase.sqliteErrorToJsError (/tmp/.mount_JoplinFq9O2U/resources/app.asar/lib/database.js:25:24)\n at JoplinDatabase.tryCall (/tmp/.mount_JoplinFq9O2U/resources/app.asar/lib/database.js:113:17)'}

```

---

<div class="post-metadata">

**Author:** ![msbentley](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/msbentley/32/1219_2.png) [@msbentley](https://discourse.joplinapp.org/u/msbentley)\
**Post date:** [21 October 2020 07:28 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/6 "2020-10-21T07:28:53Z")

</div>

Hi @laurent - everything is now working, and I can fix the broken links in MD and HTML notes - but I realise that in doing so I of course reset the note updated times, which is not ideal because immediately after import these are quite valuable meta-data.

I tried to manually set the `user_updated_time` and/or `updated_time` via the API but, logically enough, the updates reset the times to the current one.

Is there any way around this? Short of messing around in the database, I guess? Thanks!

---

<div class="post-metadata">

**Author:** ![laurent](https://avatars.discourse-cdn.com/v4/letter/l/ce7236/32.png) [@laurent](https://discourse.joplinapp.org/u/laurent)\
**Post date:** [21 October 2020 09:18 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/7 "2020-10-21T09:18:25Z")

</div>

I'd need to see the request you're making but basically every time you update the note, you should pass the required `user_updated_time` and perhaps `user_created_time` if you don't want it to change. So when you create the note, but also when you update it.

---

<div class="post-metadata">

**Author:** ![msbentley](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/msbentley/32/1219_2.png) [@msbentley](https://discourse.joplinapp.org/u/msbentley)\
**Post date:** [21 October 2020 09:20 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/8 "2020-10-21T09:20:52Z")

</div>

OK, and the UI / note list etc. will respect `user_updated_time` (rather than `updated_time`)? My aim is that I can still order the notes by updated time, ever after the re-writing of the body.

I'll try again and report back!

---

<div class="post-metadata">

**Author:** ![laurent](https://avatars.discourse-cdn.com/v4/letter/l/ce7236/32.png) [@laurent](https://discourse.joplinapp.org/u/laurent)\
**Post date:** [21 October 2020 09:24 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/9 "2020-10-21T09:24:26Z")

</div>

> [@msbentley](#):
>
> OK, and the UI / note list etc. will respect `user_updated_time` (rather than `updated_time` )? My aim is that I can still order the notes by updated time, ever after the re-writing of the body.

`user_updated_time` is what's displayed everywhere in the UI. And `updated_time` is what is used by the app to know when something has changed, in particular for sync.

---

<div class="post-metadata">

**Author:** ![msbentley](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/msbentley/32/1219_2.png) [@msbentley](https://discourse.joplinapp.org/u/msbentley)\
**Post date:** [21 October 2020 10:15 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/10 "2020-10-21T10:15:11Z")

</div>

Hmm, I'm still not having any luck. I'm making a `PUT` request to, for example:

`http://localhost:41184/notes/9039947fcd3b40728fb6f6b54f7deb9c?token=mytoken`

with the data containing the `body` and `user_updated_time`, e.g.

`{"body": "<en-note>.... </en_note>","user_updated_time": 1548754813000}`

and I get back an updated note with `"user_updated_time":1603274978951`.

Am I doing someting dumb? Thanks!

---

<div class="post-metadata">

**Author:** ![laurent](https://avatars.discourse-cdn.com/v4/letter/l/ce7236/32.png) [@laurent](https://discourse.joplinapp.org/u/laurent)\
**Post date:** [21 October 2020 17:12 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/11 "2020-10-21T17:12:59Z")

</div>

Indeed it was supported when creating a note, but not when updating one. It should work in the next pre-release.

---

<div class="post-metadata">

**Author:** ![msbentley](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/msbentley/32/1219_2.png) [@msbentley](https://discourse.joplinapp.org/u/msbentley)\
**Post date:** [21 October 2020 18:27 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/12 "2020-10-21T18:27:55Z")

</div>

Fantastic, many thanks!

---

<div class="post-metadata">

**Author:** ![msbentley](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/msbentley/32/1219_2.png) [@msbentley](https://discourse.joplinapp.org/u/msbentley)\
**Post date:** [21 October 2020 20:23 UTC](https://discourse.joplinapp.org/t/api-body-vs-body-html/11697/13 "2020-10-21T20:23:23Z")

</div>

Yep, in 1.3.8 this works a treat - with the ENEX import issues squashed, I think I'm all set tomorrow to do the Big Import! Thanks!
