---
title: "Create a note"
method: POST
path: "/public-api/v1/notes"
tags: ["Notes"]
---

# Create a note

`POST /public-api/v1/notes`

## Request

- Base URL: `https://app.hellobonsai.com`
- URL: `https://app.hellobonsai.com/public-api/v1/notes`
- Auth: one of:
  - OAuth 2
    - Authorization code: `https://app.hellobonsai.com/oauth/authorize`
    - Token URL: `https://app.hellobonsai.com/oauth/token`
  - HTTP bearer

Writes a note. `content` is the only required field.

Pass `record_type` and `record_id` together to attach the note to a
client company, a project or a contact — find the id with
`GET /public-api/v1/companies`, `GET /public-api/v1/projects` or
`GET /public-api/v1/contacts`. Leave both out and the note stands on
its own in the workspace.

## Formatting

`content` is Markdown. Bonsai converts it to the rich text the notes
editor renders, so the constructs below all survive the conversion:

- headings, `**bold**`, `*italic*`, `~~strikethrough~~`
- bullet, numbered and `- [ ]` task lists
- links, `> quotes`, `---` dividers, tables
- `inline code` and fenced code blocks

A single newline is a soft break and joins lines into one paragraph, as
in standard Markdown — leave a blank line between paragraphs. Anything
outside the list above, including raw HTML and images, is reduced to
its text.

The response returns the stored body as `content_html`, not as the
Markdown you sent. To edit this note afterwards, read `content_html`
and send the modified HTML back to
`PATCH /public-api/v1/notes/{id}` — that endpoint takes HTML, not
Markdown, so nothing is lost on the way through.

That endpoint accepts a wider set of markup than this one can produce:
images and mention spans survive an update but cannot be written here,
since the Markdown converter reduces them to their text.

## Request body

- object
  - `note` object, required
    - `content` string, required: The note body, in Markdown. Required.
    - `title` string, nullable: Note title. Defaults to empty.
    - `date` string, date, nullable: The day the note is about. Defaults to today in your account timezone.
    - `visibility` 'everyone' | 'author_only' | 'null', nullable: Who can read the note: `everyone` for the whole account, `author_only` for nobody but you. Defaults to `everyone`.
    - `record_type` 'company' | 'project' | 'contact' | 'deal' | 'null', nullable: What to attach the note to. Requires `record_id`. Omit both for a workspace note.
    - `record_id` integer, nullable: Id of the record to attach the note to. Required when `record_type` is set.

## Response `201`

The note was created.

- object
  - `data` object, required: The body of the note, returned when you write or retrieve a single note but never in a list.
    - `id` string, uuid, required: Unique identifier for the note.
    - `title` string, required: Note title. Empty when the note was written without one.
    - `date` string, date, nullable, required: The day the note is about, which is what the app sorts and groups notes by. Defaults to today in your account timezone.
    - `visibility` 'everyone' | 'author_only', required: `everyone` for a note the whole account can read, `author_only` for one only its author can. Defaults to `everyone`, and only the member who wrote the note can change it.
    - `created_by_member_id` integer, nullable, required: Team member id of the author, or `null` when they are no longer a member of your account.
    - `created_at` string, date-time, required: When the note was written.
    - `updated_at` string, date-time, required: When the note was last edited.
    - `note_links` NoteLink[], required: The records this note is attached to, leaving out any your token cannot reach. Empty for a workspace note that stands on its own.
      - `id` integer, required: Unique identifier for the attachment between the note and the record.
      - `record_id` integer, required: Id of the attached record, in the resource named by `record_type`.
      - `record_type` 'company' | 'project' | 'contact' | 'deal' | 'null', nullable, required: Which kind of record the note is attached to.
    - `content_html` string, nullable, required: The note body in the HTML the Bonsai editor renders, scrubbed of script-execution vectors. This is the field to send back to `PATCH /public-api/v1/notes/{id}`: read it, change what you need and return it, and everything you left alone is preserved. `null` only when the note has no body at all. Returned on single-note responses only, never in a list.
    - `content_plain_text` string, nullable, required: The same body with the markup removed, for when you only need to read what the note says. It cannot be sent back — the update endpoint takes `content_html`. `null` here means the body holds no text, not that the note is empty: a note containing only an image or a table returns `null` while `content_html` returns the body. Returned on single-note responses only, never in a list.
  - `meta` Meta, required: Metadata returned alongside every single-resource response.
    - `request_id` string, required: Identifier for this request. Quote it when contacting support about a specific call.

## Other responses

- `400`: The request body is missing its `note` wrapper.
- `401`: The access token is missing, expired or invalid.
- `403`: This token is not allowed to write notes.
- `422`: The note could not be saved. `blank` means `content` was empty, or `record_type` and `record_id` were not supplied together; `invalid_value` means a field was the wrong shape; `not_accessible` means `record_id` is not a record you can reach.
- `429`: Rate limit exceeded. Wait at least `Retry-After` seconds before trying again.

---

[API](https://skmtc.dev/hellobonsai/apis/bonsai-api.md) - [All operations](https://skmtc.dev/hellobonsai/apis/bonsai-api/llms.txt) - [OpenAPI document](https://skmtc.dev/hellobonsai/apis/bonsai-api/revisions/abf12ed6a8d3?raw)
