curl --request PATCH \
--url https://app.orgo.space/api/v1/user_notes/{uuid} \
--header 'Api-Token: <api-key>' \
--header 'Content-Type: application/merge-patch+json' \
--data @- <<EOF
{
"text": "Hello, you're invited to the Annual General Meeting.",
"action": "string"
}
EOFimport requests
url = "https://app.orgo.space/api/v1/user_notes/{uuid}"
payload = {
"text": "Hello, you're invited to the Annual General Meeting.",
"action": "string"
}
headers = {
"Api-Token": "<api-key>",
"Content-Type": "application/merge-patch+json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'Api-Token': '<api-key>', 'Content-Type': 'application/merge-patch+json'},
body: JSON.stringify({
text: 'Hello, you\'re invited to the Annual General Meeting.',
action: 'string'
})
};
fetch('https://app.orgo.space/api/v1/user_notes/{uuid}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.orgo.space/api/v1/user_notes/{uuid}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Hello, you\'re invited to the Annual General Meeting.',
'action' => 'string'
]),
CURLOPT_HTTPHEADER => [
"Api-Token: <api-key>",
"Content-Type: application/merge-patch+json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.orgo.space/api/v1/user_notes/{uuid}"
payload := strings.NewReader("{\n \"text\": \"Hello, you're invited to the Annual General Meeting.\",\n \"action\": \"string\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Api-Token", "<api-key>")
req.Header.Add("Content-Type", "application/merge-patch+json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://app.orgo.space/api/v1/user_notes/{uuid}")
.header("Api-Token", "<api-key>")
.header("Content-Type", "application/merge-patch+json")
.body("{\n \"text\": \"Hello, you're invited to the Annual General Meeting.\",\n \"action\": \"string\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.orgo.space/api/v1/user_notes/{uuid}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Api-Token"] = '<api-key>'
request["Content-Type"] = 'application/merge-patch+json'
request.body = "{\n \"text\": \"Hello, you're invited to the Annual General Meeting.\",\n \"action\": \"string\"\n}"
response = http.request(request)
puts response.read_body{
"uuid": "01938d8e-9c4f-7c2a-b8e1-3f7a9b8c4f12",
"text": "Hello, you're invited to the Annual General Meeting.",
"action": "string",
"dateCreated": "2026-01-15T10:30:00+00:00",
"dateUpdated": "2026-01-15T10:30:00+00:00",
"authorName": "Boston Chapter",
"authorId": 42,
"authorLogo": "https://cdn.orgo.space/tenants/acme/logo.png"
}Edit a user note
Updates the text of a user note. Allowed only for the note author or a tenant admin (ADMIN_TENANT).
curl --request PATCH \
--url https://app.orgo.space/api/v1/user_notes/{uuid} \
--header 'Api-Token: <api-key>' \
--header 'Content-Type: application/merge-patch+json' \
--data @- <<EOF
{
"text": "Hello, you're invited to the Annual General Meeting.",
"action": "string"
}
EOFimport requests
url = "https://app.orgo.space/api/v1/user_notes/{uuid}"
payload = {
"text": "Hello, you're invited to the Annual General Meeting.",
"action": "string"
}
headers = {
"Api-Token": "<api-key>",
"Content-Type": "application/merge-patch+json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'Api-Token': '<api-key>', 'Content-Type': 'application/merge-patch+json'},
body: JSON.stringify({
text: 'Hello, you\'re invited to the Annual General Meeting.',
action: 'string'
})
};
fetch('https://app.orgo.space/api/v1/user_notes/{uuid}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.orgo.space/api/v1/user_notes/{uuid}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Hello, you\'re invited to the Annual General Meeting.',
'action' => 'string'
]),
CURLOPT_HTTPHEADER => [
"Api-Token: <api-key>",
"Content-Type: application/merge-patch+json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.orgo.space/api/v1/user_notes/{uuid}"
payload := strings.NewReader("{\n \"text\": \"Hello, you're invited to the Annual General Meeting.\",\n \"action\": \"string\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Api-Token", "<api-key>")
req.Header.Add("Content-Type", "application/merge-patch+json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://app.orgo.space/api/v1/user_notes/{uuid}")
.header("Api-Token", "<api-key>")
.header("Content-Type", "application/merge-patch+json")
.body("{\n \"text\": \"Hello, you're invited to the Annual General Meeting.\",\n \"action\": \"string\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.orgo.space/api/v1/user_notes/{uuid}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Api-Token"] = '<api-key>'
request["Content-Type"] = 'application/merge-patch+json'
request.body = "{\n \"text\": \"Hello, you're invited to the Annual General Meeting.\",\n \"action\": \"string\"\n}"
response = http.request(request)
puts response.read_body{
"uuid": "01938d8e-9c4f-7c2a-b8e1-3f7a9b8c4f12",
"text": "Hello, you're invited to the Annual General Meeting.",
"action": "string",
"dateCreated": "2026-01-15T10:30:00+00:00",
"dateUpdated": "2026-01-15T10:30:00+00:00",
"authorName": "Boston Chapter",
"authorId": 42,
"authorLogo": "https://cdn.orgo.space/tenants/acme/logo.png"
}Authorizations
Server-to-server authentication. Generate a token in the admin UI at
Settings → Developers → API Access. Send the raw token in the
Api-Token header — there is no Bearer prefix.
Tokens can be marked read-only at creation time, in which case the API
rejects any non-GET request with 403 Forbidden.
Path Parameters
UserNote identifier
Body
The updated UserNote resource
A single, attributed note left on a User by HR/Financial staff. Mirrors ContactNote: an append-style thread where each entry records its author and timestamps.
Unlike ContactNote there is no legacy blob to migrate, but $author stays nullable so a deleted staff account (onDelete SET NULL) does not take the note text with it.
Notes are NOT serialized into user_read: that group is served on the plain
profile GET, the user list and self-profile-update, so embedding them would
expose staff notes to the subject and to peers. They are read only through
the UserNote collection, gated by UserNoteCollectionExtension.
Tenant is mapped explicitly (not delegated to the subject user) because
UserNote is an API Platform resource: the tenant-isolation Doctrine
extensions emit WHERE o.tenant = :tenant, which requires a real column.
512Response
UserNote resource updated
A single, attributed note left on a User by HR/Financial staff. Mirrors ContactNote: an append-style thread where each entry records its author and timestamps.
Unlike ContactNote there is no legacy blob to migrate, but $author stays nullable so a deleted staff account (onDelete SET NULL) does not take the note text with it.
Notes are NOT serialized into user_read: that group is served on the plain
profile GET, the user list and self-profile-update, so embedding them would
expose staff notes to the subject and to peers. They are read only through
the UserNote collection, gated by UserNoteCollectionExtension.
Tenant is mapped explicitly (not delegated to the subject user) because
UserNote is an API Platform resource: the tenant-isolation Doctrine
extensions emit WHERE o.tenant = :tenant, which requires a real column.

