Record Observations
curl --request POST \
--url https://api.opennous.cloud/v2/observations \
--header 'Content-Type: application/json' \
--data '
{
"focus": "<string>",
"observations": [
{
"kind": "<string>",
"property": "<string>",
"value": "<any>",
"source": "<string>",
"method": "<string>",
"observed_at": {},
"external_id": "<string>",
"raw": {}
}
]
}
'import requests
url = "https://api.opennous.cloud/v2/observations"
payload = {
"focus": "<string>",
"observations": [
{
"kind": "<string>",
"property": "<string>",
"value": "<any>",
"source": "<string>",
"method": "<string>",
"observed_at": {},
"external_id": "<string>",
"raw": {}
}
]
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
focus: '<string>',
observations: [
{
kind: '<string>',
property: '<string>',
value: '<any>',
source: '<string>',
method: '<string>',
observed_at: {},
external_id: '<string>',
raw: {}
}
]
})
};
fetch('https://api.opennous.cloud/v2/observations', 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://api.opennous.cloud/v2/observations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'focus' => '<string>',
'observations' => [
[
'kind' => '<string>',
'property' => '<string>',
'value' => '<any>',
'source' => '<string>',
'method' => '<string>',
'observed_at' => [
],
'external_id' => '<string>',
'raw' => [
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/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://api.opennous.cloud/v2/observations"
payload := strings.NewReader("{\n \"focus\": \"<string>\",\n \"observations\": [\n {\n \"kind\": \"<string>\",\n \"property\": \"<string>\",\n \"value\": \"<any>\",\n \"source\": \"<string>\",\n \"method\": \"<string>\",\n \"observed_at\": {},\n \"external_id\": \"<string>\",\n \"raw\": {}\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.opennous.cloud/v2/observations")
.header("Content-Type", "application/json")
.body("{\n \"focus\": \"<string>\",\n \"observations\": [\n {\n \"kind\": \"<string>\",\n \"property\": \"<string>\",\n \"value\": \"<any>\",\n \"source\": \"<string>\",\n \"method\": \"<string>\",\n \"observed_at\": {},\n \"external_id\": \"<string>\",\n \"raw\": {}\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.opennous.cloud/v2/observations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"focus\": \"<string>\",\n \"observations\": [\n {\n \"kind\": \"<string>\",\n \"property\": \"<string>\",\n \"value\": \"<any>\",\n \"source\": \"<string>\",\n \"method\": \"<string>\",\n \"observed_at\": {},\n \"external_id\": \"<string>\",\n \"raw\": {}\n }\n ]\n}"
response = http.request(request)
puts response.read_bodyObservations
Record Observations
Record what happened. You observe; Nous derives the claims.
POST
/
v2
/
observations
Record Observations
curl --request POST \
--url https://api.opennous.cloud/v2/observations \
--header 'Content-Type: application/json' \
--data '
{
"focus": "<string>",
"observations": [
{
"kind": "<string>",
"property": "<string>",
"value": "<any>",
"source": "<string>",
"method": "<string>",
"observed_at": {},
"external_id": "<string>",
"raw": {}
}
]
}
'import requests
url = "https://api.opennous.cloud/v2/observations"
payload = {
"focus": "<string>",
"observations": [
{
"kind": "<string>",
"property": "<string>",
"value": "<any>",
"source": "<string>",
"method": "<string>",
"observed_at": {},
"external_id": "<string>",
"raw": {}
}
]
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
focus: '<string>',
observations: [
{
kind: '<string>',
property: '<string>',
value: '<any>',
source: '<string>',
method: '<string>',
observed_at: {},
external_id: '<string>',
raw: {}
}
]
})
};
fetch('https://api.opennous.cloud/v2/observations', 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://api.opennous.cloud/v2/observations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'focus' => '<string>',
'observations' => [
[
'kind' => '<string>',
'property' => '<string>',
'value' => '<any>',
'source' => '<string>',
'method' => '<string>',
'observed_at' => [
],
'external_id' => '<string>',
'raw' => [
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/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://api.opennous.cloud/v2/observations"
payload := strings.NewReader("{\n \"focus\": \"<string>\",\n \"observations\": [\n {\n \"kind\": \"<string>\",\n \"property\": \"<string>\",\n \"value\": \"<any>\",\n \"source\": \"<string>\",\n \"method\": \"<string>\",\n \"observed_at\": {},\n \"external_id\": \"<string>\",\n \"raw\": {}\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.opennous.cloud/v2/observations")
.header("Content-Type", "application/json")
.body("{\n \"focus\": \"<string>\",\n \"observations\": [\n {\n \"kind\": \"<string>\",\n \"property\": \"<string>\",\n \"value\": \"<any>\",\n \"source\": \"<string>\",\n \"method\": \"<string>\",\n \"observed_at\": {},\n \"external_id\": \"<string>\",\n \"raw\": {}\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.opennous.cloud/v2/observations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"focus\": \"<string>\",\n \"observations\": [\n {\n \"kind\": \"<string>\",\n \"property\": \"<string>\",\n \"value\": \"<any>\",\n \"source\": \"<string>\",\n \"method\": \"<string>\",\n \"observed_at\": {},\n \"external_id\": \"<string>\",\n \"raw\": {}\n }\n ]\n}"
response = http.request(request)
puts response.read_bodyThe only write verb in the context graph. Agents never overwrite, they record observations. Nous derives the new facts automatically from the full observation history and tells you which were recomputed.
Request
curl -X POST https://api.opennous.cloud/v2/observations \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"focus": "sarah@acme.com",
"observations": [
{
"kind": "event",
"property": "interaction.email_sent",
"value": { "subject": "Q3 pricing", "body_snippet": "..." }
},
{
"kind": "state",
"property": "intent",
"value": "evaluating",
"source": "agent"
}
]
}'
Body
string
required
Entity UUID, email, domain, or LinkedIn URL. Not a bare name — writes need a precise identifier so the entity can be created if it doesn’t exist yet.
array
required
One or more observations to append. Each:
Show observation
Show observation
string
required
"event" for an interaction (email sent, call held, page visited) or "state" for a fact (title is VP Sales, intent is evaluating).string
required
Namespaced — events use
interaction.<type> (e.g. interaction.email_sent); state uses bare names (e.g. title, intent, stage).any
The observation payload. For events: detail object. For state: the value (use
null to assert the fact ended — they left the role, etc.).string
Where the signal came from. Default:
"agent".string
How it was captured. Default:
"api".string (ISO 8601)
When it happened. Default: now.
string
Dedup key from the upstream system (e.g. the HubSpot engagement ID).
object
The full upstream payload, stored for audit. Not interpreted.
Response
{
"entity_id": "a1b2c3d4-...",
"recorded": 2,
"claims_recomputed": ["intent"]
}
claims_recomputed lists the state properties whose claim was re-derived after this batch — your downstream UI can refetch only those.
The observation model
You’re appending to an immutable, append-only context graph. Two reasons:- The graph self-heals. When a new observation contradicts an old one, the affected facts recompute and the belief shifts. Nothing is ever “lost.”
- Every claim is auditable —
epistemic_class+sourceson every claim let your agent (and your audit log) see exactly which observations support it.
null value on a state observation to assert the fact ended — they left the company, the deal closed-lost, the email bounced.⌘I