curl --request PUT \
--url https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"scope": "personal",
"path": "web-app.md",
"content": "# Web app\n\n- Run `bun run test` before opening a pull request.\n"
}
'import requests
url = "https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file"
payload = {
"scope": "personal",
"path": "web-app.md",
"content": "# Web app
- Run `bun run test` before opening a pull request.
"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
scope: 'personal',
path: 'web-app.md',
content: '# Web app\n\n- Run `bun run test` before opening a pull request.\n'
})
};
fetch('https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file', 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.reasonmachines.com/v3/organizations/{orgId}/memory/file",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'scope' => 'personal',
'path' => 'web-app.md',
'content' => '# Web app
- Run `bun run test` before opening a pull request.
'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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.reasonmachines.com/v3/organizations/{orgId}/memory/file"
payload := strings.NewReader("{\n \"scope\": \"personal\",\n \"path\": \"web-app.md\",\n \"content\": \"# Web app\\n\\n- Run `bun run test` before opening a pull request.\\n\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.put("https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"scope\": \"personal\",\n \"path\": \"web-app.md\",\n \"content\": \"# Web app\\n\\n- Run `bun run test` before opening a pull request.\\n\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"scope\": \"personal\",\n \"path\": \"web-app.md\",\n \"content\": \"# Web app\\n\\n- Run `bun run test` before opening a pull request.\\n\"\n}"
response = http.request(request)
puts response.read_body{
"scope": "personal",
"file": {
"path": "<string>",
"content": "<string>",
"byte_length": 123,
"updated_at": "2023-11-07T05:31:56Z",
"revision_id": "<string>"
},
"updated": true
}{
"error": "prompt_required"
}{
"error": "missing_bearer",
"message": "Authorization required"
}{
"error": "missing_scope",
"required_scope": "sessions:read"
}{
"error": "last_owner"
}{
"error": "<string>",
"message": "<string>",
"required_scope": "<string>"
}{
"error": {
"type": "rate_limited",
"message": "This API key exceeded its request-rate limit"
}
}Write a memory file
Creates a file or replaces its whole text. Reasons read the change from their next Session on: MEMORY.md is in every Session’s starting context, so keep it short and put detail in topic notes, which a Session reads when it needs them.
Personal memory is the caller’s own; team memory takes direct writes only from a Workspace owner or admin (403 for other members). The change is stored as a revision under the caller’s name with no source Session, so it shows in memory history and can be restored. Paths are normalized (lower case, .md added); empty text (for a note), text over the size limit (32 KiB a note, 12 KiB MEMORY.md), or text holding a secret or instructions aimed at a later Session is refused with 422, and a new note in a folder that already holds 200 answers 409. Personal memory that its owner turned off cannot change (409 memory_disabled).
memory:writecurl --request PUT \
--url https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"scope": "personal",
"path": "web-app.md",
"content": "# Web app\n\n- Run `bun run test` before opening a pull request.\n"
}
'import requests
url = "https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file"
payload = {
"scope": "personal",
"path": "web-app.md",
"content": "# Web app
- Run `bun run test` before opening a pull request.
"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
scope: 'personal',
path: 'web-app.md',
content: '# Web app\n\n- Run `bun run test` before opening a pull request.\n'
})
};
fetch('https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file', 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.reasonmachines.com/v3/organizations/{orgId}/memory/file",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'scope' => 'personal',
'path' => 'web-app.md',
'content' => '# Web app
- Run `bun run test` before opening a pull request.
'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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.reasonmachines.com/v3/organizations/{orgId}/memory/file"
payload := strings.NewReader("{\n \"scope\": \"personal\",\n \"path\": \"web-app.md\",\n \"content\": \"# Web app\\n\\n- Run `bun run test` before opening a pull request.\\n\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.put("https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"scope\": \"personal\",\n \"path\": \"web-app.md\",\n \"content\": \"# Web app\\n\\n- Run `bun run test` before opening a pull request.\\n\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/v3/organizations/{orgId}/memory/file")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"scope\": \"personal\",\n \"path\": \"web-app.md\",\n \"content\": \"# Web app\\n\\n- Run `bun run test` before opening a pull request.\\n\"\n}"
response = http.request(request)
puts response.read_body{
"scope": "personal",
"file": {
"path": "<string>",
"content": "<string>",
"byte_length": 123,
"updated_at": "2023-11-07T05:31:56Z",
"revision_id": "<string>"
},
"updated": true
}{
"error": "prompt_required"
}{
"error": "missing_bearer",
"message": "Authorization required"
}{
"error": "missing_scope",
"required_scope": "sessions:read"
}{
"error": "last_owner"
}{
"error": "<string>",
"message": "<string>",
"required_scope": "<string>"
}{
"error": {
"type": "rate_limited",
"message": "This API key exceeded its request-rate limit"
}
}Authorizations
Your Reason API key from Settings › API keys. New keys use reason_; legacy ara_ keys remain accepted. Keys are capability-scoped: run, mcp:read, mcp:write, secrets:read, secrets:write, sessions:read, sessions:debug, knowledge:read, memory:read, memory:write, skills:read, skills:write, repos:read, repos:write, reviews:read, reviews:write, deployment:read, analytics:read, org:read, org:write, attachments:read, attachments:write, guardrails:read, guardrails:write, network:read, network:write, automations:read, automations:write, agent_auth:read. network:read and network:write are opt-in, excluded from default keys. network:read reads the saved workspace network policy; network:write replaces custom allowed hosts and requires a current organization owner/admin. Legacy project PATCH requests containing network_allowed_hosts also require network:write plus their existing run scope and project management permission; saved project hosts do not affect current session egress. Only owners/admins can mint or manage keys with network:write; keys cannot grant themselves more authority. See /docs/network-policies for replacement semantics and runtime applicability. mcp:write manages MCP server configuration only; it does not authorize remote MCP-tool execution. sessions:read reads sessions, including the assistant, reasoning and tool activity in their events. sessions:debug is privileged: only for organization owners/admins, it expands session events to the full diagnostic projection (diagnostic event kinds, status text and raw event metadata).
Path Parameters
Organization id or slug. Resolve it with GET /v3/self.
Body
personal: the memory of the person the API key or OAuth grant belongs to, private to them. team: the Workspace's shared team memory, which every member's Sessions read.
personal, team The file's path within the scope: MEMORY.md (the index) or a note such as web-app.md. A name without an extension gets .md, and paths are lower case, so Web-App and web-app.md are one note. Personal notes may sit in up to three folders (projects/web-app.md); team notes sit at the top or in a place folder such as reasons/<key>/. A memory:/ or team:/ prefix is accepted and ignored.
The file's complete new text; it replaces what the file holds. A note needs some text and at most 32 KiB; MEMORY.md at most 12 KiB. Text holding a secret, or instructions aimed at a later Session, is refused.
The revision_id of the file as last read: the write is refused with 409 when the file has changed since. null requires that the file does not exist yet. Leave it out to replace whatever the file holds.
Response
The file as stored.
personal: the memory of the person the API key or OAuth grant belongs to, private to them. team: the Workspace's shared team memory, which every member's Sessions read.
personal, team Show child attributes
Show child attributes
False when the file already held this text, so nothing changed.

