MemorySync
API Reference

Synced Objects

List what a connection brought in, inspect one object in detail, and control it individually: pause a noisy one, re-extract after a prompt change, delete just its memories.

Operations on this page

OperationMethod and pathPythonNode.js
List a connection's objectsGET …/connections/{connection_id}/objectsconnections.objectsconnections.objects
List with richer filtersGET …/connections/{connection_id}/objects/v2connections.objects_v2connections.objectsV2
Act on many at oncePOST …/connections/{connection_id}/objects/bulkconnections.bulk_object_actionconnections.bulkObjectAction
Get one objectGET /api/v2/integrations/objects/{object_id}objects.getobjects.get
Content analysisGET …/objects/{object_id}/analysisobjects.analysisobjects.analysis
Audit trailGET …/objects/{object_id}/auditobjects.auditobjects.audit
Change historyGET …/objects/{object_id}/historyobjects.historyobjects.history
Memory extraction stateGET …/objects/{object_id}/memory-statusobjects.memory_statusobjects.memoryStatus
Structured-data statsGET …/objects/{object_id}/structured-statsobjects.structured_statsobjects.structuredStats
Evaluate extractionPOST …/objects/{object_id}/evaluateobjects.evaluateobjects.evaluate
Pause syncingPOST …/objects/{object_id}/pauseobjects.pauseobjects.pause
Resume syncingPOST …/objects/{object_id}/resumeobjects.resumeobjects.resume
Re-extract memoriesPOST …/objects/{object_id}/reextractobjects.reextractobjects.reextract
Re-read from the sourcePOST …/objects/{object_id}/resyncobjects.resyncobjects.resync
Delete its memoriesDELETE …/objects/{object_id}/memoriesobjects.delete_memoriesobjects.deleteMemories

Authentication and scope

RequirementContract
CredentialAn API key sent as X-API-Key. Connector operations are not end-user scoped.
Read scopeintegrations:read for every GET.
Write scopeintegrations:write for every POST, PUT, PATCH and DELETE.
TenantDerived from the authenticated key. There is no tenant parameter to pass or to get wrong.
X-End-User-IDNot used. A connection belongs to the organization, not to one end user.

Object ids and who may act

Two things on this page differ from the rest of the connector API, and both produce confusing failures if missed.

RuleDetail
Object ids are integersEvery {object_id} is an integer, not an opaque string. 71412, not "obj_71412". A non-numeric id is a 422, not a 404.
object_ids are integers tooThe bulk action takes [71412, 71413]. A list of strings is rejected.
Writes need an admin roleEvery write here — evaluate, pause, resume, resync, delete_memories, and the bulk action — additionally requires the authenticated principal to be admin or owner. The integrations:write scope alone gets a 403.
audit needs an admin roleIt is the one read on this page that does. Every other read needs only integrations:read.

What an object is

An object is one thing read from the source — a Slack message, a Drive file, an S3 key, a Granola note. It is not a memory. One object can produce several memories, or none, and the two are tracked separately so you can re-extract without re-reading, or delete memories without losing the record that the object was seen.

Object to memory
  1. 1Source item

    A file, message or note in the external system.

  2. 2Synced object

    MemorySync's record of it, with a content hash so an unchanged item is not re-read.

  3. 3Extraction

    Text is parsed and passed to extraction.

  4. 4Memories

    Zero or more memories, each retrievable through the memory API.

1. List what came in

Two list operations exist. objects is the plain listing; objects_v2 adds filtering and richer per-object fields. Prefer objects_v2 for a UI, and objects when you only need ids.

import os
from memorysync import MemorySyncClient
client = MemorySyncClient(
api_key=os.environ["MEMORYSYNC_API_KEY"],
base_url="https://api.memorysync.io",
)
page = client.connections.objects_v2(
"conn_8f21a4",
status="synced",
sort_by="last_synced_at",
sort_order="desc",
limit=50,
)
print(page["total"], page["has_more"], page["stats"])
for obj in page["objects"]:
print(obj["id"], obj["title"], obj["memories_count"], obj["sync_status"])
GET/api/v2/integrations/connections/{connection_id}/objects
200 OK
GET/api/v2/integrations/connections/{connection_id}/objects/v2
200 OK
ParameterContract
statusOptional. Filter by sync status.
object_typeOptional. Filter by source object type.
searchOptional. Free-text match.
sort_byOne of last_synced_at (default), title, source_created_at. Anything else is a 422.
sort_orderdesc (default) or asc.
limit, offsetDefaults 50 and 0; limit is capped at 200.
Response fieldMeaning
objectsThe page of objects.
totalHow many match the filter.
has_moreWhether another page exists. Page on this rather than comparing counts.
statsCounts by state: synced, skipped, failed, paused — for the whole connection, not the page.

2. Inspect one object

The detail response wraps three things together: the object itself, the memories it produced, and its sync history. The object is nested under object rather than being the response body.

import os
from memorysync import MemorySyncClient
client = MemorySyncClient(
api_key=os.environ["MEMORYSYNC_API_KEY"],
base_url="https://api.memorysync.io",
)
detail = client.objects.get(71412)
obj = detail["object"]
print(obj["source_path"], obj["sync_status"], obj["memories_count"])
for memory in detail["memories"]:
print(memory["memory_id"], memory["extraction_method"])
for event in detail["sync_history"]:
print(event["event_type"], event["created_at"])
GET/api/v2/integrations/objects/{object_id}
200 OK
Response fieldContains
objectThe object record — source_path, sync_status, skip_reason, sync_paused, memories_count, memory_ids, and the structured-content summary.
memoriesOne entry per memory produced, with memory_id, extraction_method and chunk position.
sync_historySync events, including the content hashes that decide whether a re-read is needed.

3. Find out why it produced nothing

An object that synced but yielded no memories is the most common connector question. Four read operations answer it, and they answer different halves of it.

import os
from memorysync import MemorySyncClient
client = MemorySyncClient(
api_key=os.environ["MEMORYSYNC_API_KEY"],
base_url="https://api.memorysync.io",
)
# Extraction state, the candidates it considered, and whether a retry is allowed.
status = client.objects.memory_status(71412)
print(status["memories_created"], status["can_reextract"])
if status["extraction_status"]:
print(status["extraction_status"]["explanation"], status["extraction_status"]["skip_reason"])
for candidate in status["candidates"]:
print(candidate["decision"], candidate["discard_reason"], candidate["importance_score"])
# What the content itself looked like — the answer when nothing was extractable.
analysis = client.objects.analysis(71412)
print(analysis["extraction_path_label"], analysis["failure_classification"])
print(analysis["content_source"], analysis["content_char_count"], analysis["ocr_used"])
# Rows and columns, for tabular sources.
stats = client.objects.structured_stats(71412)
print(stats["is_structured"], stats["memory_explanation"]["reason"])
# What changed, and when.
history = client.objects.history(71412, limit=20)
print(history["total_events"])
for event in history["events"]:
print(event["timestamp"], event["event_type"], event["description"])
GET/api/v2/integrations/objects/{object_id}/memory-status
200 OK
GET/api/v2/integrations/objects/{object_id}/analysis
200 OK
GET/api/v2/integrations/objects/{object_id}/structured-stats
200 OK
GET/api/v2/integrations/objects/{object_id}/history
200 OK
QuestionOperation
Did extraction run, and what did it produce?memory_status
Was there anything extractable in the content at all?analysis
How many rows and columns did this spreadsheet actually have?structured_stats
Has this object changed since it was first read?history
Who or what touched this object?audit

4. Read the audit trail

audit records the actions taken on this object and by whom, which is what an access review or an incident investigation needs. Entries arrive under events.

import os
from memorysync import MemorySyncClient
client = MemorySyncClient(
api_key=os.environ["MEMORYSYNC_API_KEY"],
base_url="https://api.memorysync.io",
)
for event in client.objects.audit(71412, limit=50)["events"]:
print(event)
GET/api/v2/integrations/objects/{object_id}/audit
200 OK
ParameterContract
limitOptional. Defaults to 50, capped at 200.

5. Stop a noisy object

Pause keeps the object and its memories but stops future syncs from reading it again. Use it for the CI-status channel or the auto-generated report that produces volume and no value.

import os
from memorysync import MemorySyncClient
client = MemorySyncClient(
api_key=os.environ["MEMORYSYNC_API_KEY"],
base_url="https://api.memorysync.io",
)
result = client.objects.pause(71412)
print(result["success"], result["sync_paused"], result["message"])
# …later
client.objects.resume(71412)
POST/api/v2/integrations/objects/{object_id}/pause
200 OK
POST/api/v2/integrations/objects/{object_id}/resume
200 OK
Response fieldMeaning
successWhether the action applied.
messageA human-readable outcome.
sync_pausedThe resulting paused state. Present on pause and resume.
job_idSet when the action queued background work, as resync does. Null otherwise.
deleted_countSet by delete_memories. Null otherwise.

6. Re-extract, or re-read

Two different repairs, and the distinction matters for both cost and correctness:

import os
from memorysync import MemorySyncClient
client = MemorySyncClient(
api_key=os.environ["MEMORYSYNC_API_KEY"],
base_url="https://api.memorysync.io",
)
# The stored text is fine; run extraction over it again.
queued = client.objects.reextract(71412)
print(queued["message"], queued["object_id"])
# The source changed, or the stored copy is wrong; read it again.
result = client.objects.resync(71412)
print(result["job_id"])
POST/api/v2/integrations/objects/{object_id}/reextract
202 Accepted
POST/api/v2/integrations/objects/{object_id}/resync
202 Accepted
Re-extractRe-sync
Contacts the providerNoYes
Uses provider rate limitNoYes
Re-runs extractionYesYes
Right whenThe extraction prompt or the ontology changed.The source document itself changed.

7. Run the extraction evaluation

evaluate runs the promotion evaluation over this one object and reports what came of it, with the reason codes behind the decision. It is how you check an ontology or prompt change on a single object before re-extracting a whole connection.

import os
from memorysync import MemorySyncClient
client = MemorySyncClient(
api_key=os.environ["MEMORYSYNC_API_KEY"],
base_url="https://api.memorysync.io",
)
result = client.objects.evaluate(71412)
print(result["result"], result["reason_codes"])
print(result["candidates_found"], "candidates ->", result["memories_created"], "memories")
print(result["attempt_id"], result["processing_state"])
POST/api/v2/integrations/objects/{object_id}/evaluate
200 OK
Response fieldMeaning
resultThe outcome of the evaluation.
reason_codesWhy. This is the field to surface to whoever is tuning extraction.
candidates_found, memories_createdHow much was considered, and how much was kept.
attempt_idThe recorded attempt, so the run can be correlated later.
processing_stateWhere processing got to.

8. Delete just the memories

Removes what this object produced while keeping the object record, so the next sync does not treat it as new and import it again.

import os
from memorysync import MemorySyncClient
client = MemorySyncClient(
api_key=os.environ["MEMORYSYNC_API_KEY"],
base_url="https://api.memorysync.io",
)
result = client.objects.delete_memories(71412)
print(result["deleted_count"], result["message"])
DELETE/api/v2/integrations/objects/{object_id}/memories
200 OK

9. Do it to many at once

One request, one action, many objects. Use it instead of a client-side loop: a loop of two hundred calls will meet a rate limit and leave the batch half-applied.

import os
from memorysync import MemorySyncClient
client = MemorySyncClient(
api_key=os.environ["MEMORYSYNC_API_KEY"],
base_url="https://api.memorysync.io",
)
result = client.connections.bulk_object_action(
"conn_8f21a4",
action="pause",
object_ids=[71412, 71413, 71414],
)
print(result["success_count"], result["failed_count"])
for item in result["results"]:
if not item["success"]:
print("failed:", item["object_id"], item["error"])
POST/api/v2/integrations/connections/{connection_id}/objects/bulk
200 OK
FieldContract
actionRequired. Exactly one of pause, resume, delete_memories. Note that reextract and resync are not bulk actions.
object_idsRequired. A list of integers.
Response fieldMeaning
success_count, failed_countTotals.
resultsOne entry per object: object_id, success, and error when it failed.

Billing

Re-extract and re-sync are billed for the memories they create, like any add. Pause, resume, delete-memories and every read on this page are not billed. A bulk re-extract over a large connection is the most expensive operation here — check one object with evaluate first.

Errors and next action

StatusMeaningNext action
401Missing, malformed or inactive API key.Check server configuration without printing the key.
403The key lacks integrations:read or integrations:write.Grant the scope on the key, or use a key that has it.
404The connection, object or job is not visible to this tenant.Confirm the identifier belongs to this organization.
409The connection is in a state that forbids the operation.Read the connection status first and act on it.
429Rate limited, either by MemorySync or by the upstream provider.Back off; do not tighten a polling loop in response.
5xxService failure.Treat a write outcome as uncertain and reconcile by reading the connection back.