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
| Operation | Method and path | Python | Node.js |
|---|---|---|---|
| List a connection's objects | GET …/connections/{connection_id}/objects | connections.objects | connections.objects |
| List with richer filters | GET …/connections/{connection_id}/objects/v2 | connections.objects_v2 | connections.objectsV2 |
| Act on many at once | POST …/connections/{connection_id}/objects/bulk | connections.bulk_object_action | connections.bulkObjectAction |
| Get one object | GET /api/v2/integrations/objects/{object_id} | objects.get | objects.get |
| Content analysis | GET …/objects/{object_id}/analysis | objects.analysis | objects.analysis |
| Audit trail | GET …/objects/{object_id}/audit | objects.audit | objects.audit |
| Change history | GET …/objects/{object_id}/history | objects.history | objects.history |
| Memory extraction state | GET …/objects/{object_id}/memory-status | objects.memory_status | objects.memoryStatus |
| Structured-data stats | GET …/objects/{object_id}/structured-stats | objects.structured_stats | objects.structuredStats |
| Evaluate extraction | POST …/objects/{object_id}/evaluate | objects.evaluate | objects.evaluate |
| Pause syncing | POST …/objects/{object_id}/pause | objects.pause | objects.pause |
| Resume syncing | POST …/objects/{object_id}/resume | objects.resume | objects.resume |
| Re-extract memories | POST …/objects/{object_id}/reextract | objects.reextract | objects.reextract |
| Re-read from the source | POST …/objects/{object_id}/resync | objects.resync | objects.resync |
| Delete its memories | DELETE …/objects/{object_id}/memories | objects.delete_memories | objects.deleteMemories |
Authentication and scope
| Requirement | Contract |
|---|---|
| Credential | An API key sent as X-API-Key. Connector operations are not end-user scoped. |
| Read scope | integrations:read for every GET. |
| Write scope | integrations:write for every POST, PUT, PATCH and DELETE. |
| Tenant | Derived from the authenticated key. There is no tenant parameter to pass or to get wrong. |
X-End-User-ID | Not 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.
| Rule | Detail |
|---|---|
| Object ids are integers | Every {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 too | The bulk action takes [71412, 71413]. A list of strings is rejected. |
| Writes need an admin role | Every 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 role | It 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.
- 1Source item
A file, message or note in the external system.
- 2Synced object
MemorySync's record of it, with a content hash so an unchanged item is not re-read.
- 3Extraction
Text is parsed and passed to extraction.
- 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 osfrom memorysync import MemorySyncClientclient = 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"])
| Parameter | Contract |
|---|---|
status | Optional. Filter by sync status. |
object_type | Optional. Filter by source object type. |
search | Optional. Free-text match. |
sort_by | One of last_synced_at (default), title, source_created_at. Anything else is a 422. |
sort_order | desc (default) or asc. |
limit, offset | Defaults 50 and 0; limit is capped at 200. |
| Response field | Meaning |
|---|---|
objects | The page of objects. |
total | How many match the filter. |
has_more | Whether another page exists. Page on this rather than comparing counts. |
stats | Counts 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 osfrom memorysync import MemorySyncClientclient = 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"])
| Response field | Contains |
|---|---|
object | The object record — source_path, sync_status, skip_reason, sync_paused, memories_count, memory_ids, and the structured-content summary. |
memories | One entry per memory produced, with memory_id, extraction_method and chunk position. |
sync_history | Sync 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 osfrom memorysync import MemorySyncClientclient = 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"])
| Question | Operation |
|---|---|
| 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 osfrom memorysync import MemorySyncClientclient = 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)
| Parameter | Contract |
|---|---|
limit | Optional. 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 osfrom memorysync import MemorySyncClientclient = 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"])# …laterclient.objects.resume(71412)
| Response field | Meaning |
|---|---|
success | Whether the action applied. |
message | A human-readable outcome. |
sync_paused | The resulting paused state. Present on pause and resume. |
job_id | Set when the action queued background work, as resync does. Null otherwise. |
deleted_count | Set by delete_memories. Null otherwise. |
6. Re-extract, or re-read
Two different repairs, and the distinction matters for both cost and correctness:
import osfrom memorysync import MemorySyncClientclient = 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"])
| Re-extract | Re-sync | |
|---|---|---|
| Contacts the provider | No | Yes |
| Uses provider rate limit | No | Yes |
| Re-runs extraction | Yes | Yes |
| Right when | The 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 osfrom memorysync import MemorySyncClientclient = 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"])
| Response field | Meaning |
|---|---|
result | The outcome of the evaluation. |
reason_codes | Why. This is the field to surface to whoever is tuning extraction. |
candidates_found, memories_created | How much was considered, and how much was kept. |
attempt_id | The recorded attempt, so the run can be correlated later. |
processing_state | Where 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 osfrom memorysync import MemorySyncClientclient = 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"])
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 osfrom memorysync import MemorySyncClientclient = 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"])
| Field | Contract |
|---|---|
action | Required. Exactly one of pause, resume, delete_memories. Note that reextract and resync are not bulk actions. |
object_ids | Required. A list of integers. |
| Response field | Meaning |
|---|---|
success_count, failed_count | Totals. |
results | One 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
| Status | Meaning | Next action |
|---|---|---|
401 | Missing, malformed or inactive API key. | Check server configuration without printing the key. |
403 | The key lacks integrations:read or integrations:write. | Grant the scope on the key, or use a key that has it. |
404 | The connection, object or job is not visible to this tenant. | Confirm the identifier belongs to this organization. |
409 | The connection is in a state that forbids the operation. | Read the connection status first and act on it. |
429 | Rate limited, either by MemorySync or by the upstream provider. | Back off; do not tighten a polling loop in response. |
5xx | Service failure. | Treat a write outcome as uncertain and reconcile by reading the connection back. |