Connection Lifecycle
Create, read, update, repair and remove a connection to an external source. These eight operations are identical for every provider — the provider-specific configuration lives on its own page.
Operations on this page
| Operation | Method and path | Python | Node.js |
|---|---|---|---|
| List connections | GET /api/v2/integrations/connections | connections.list | connections.list |
| Get one connection | GET /api/v2/integrations/connections/{connection_id} | connections.get | connections.get |
| Create with an API key | POST /api/v2/integrations/connections/api-key | connections.create_with_api_key | connections.createWithApiKey |
| Create with credentials | POST /api/v2/integrations/connections/credentials | connections.create_with_credentials | connections.createWithCredentials |
| Update a connection | PATCH /api/v2/integrations/connections/{connection_id} | connections.update | connections.update |
| Delete a connection | DELETE /api/v2/integrations/connections/{connection_id} | connections.delete | connections.delete |
| Re-authorise | POST /api/v2/integrations/connections/{connection_id}/reconnect | connections.reconnect | connections.reconnect |
| Purge synced data | POST /api/v2/integrations/connections/{connection_id}/purge | connections.purge | connections.purge |
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. |
The shape of a connection
- 11. Create
Either by API key or credentials here, or by OAuth on the Providers & OAuth page.
- 22. Configure
Choose what to sync using the connector's own configuration page.
- 33. Sync
Trigger a sync and watch the job. Covered on Sync & Jobs.
- 44. Operate
Inspect objects, pause noisy ones, re-extract after a prompt change.
- 55. End
Purge keeps the connection and removes the data; delete removes both.
1. Choose how to authenticate
How does the provider authenticate?
A user grants access
Slack, Google Drive, Notion, OneDrive.
Use: Use OAuth initiate; do not use the two create operations here.
A long-lived API key
A provider that issues a token you hold.
Use: Use create_with_api_key.
A credential set
Amazon S3 and anything needing more than one secret.
Use: Use create_with_credentials.
2. Create the connection
Create with a single API key. The argument is provider; the field on the wire is provider_id, and both SDKs handle that translation.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)connection = client.connections.create_with_api_key(provider="granola",api_key=os.environ["GRANOLA_API_KEY"],)print(connection["connection_id"], connection["status"])
Create with a credential set, which is what Amazon S3 needs:
connection = client.connections.create_with_credentials(provider="s3",credentials={"access_key_id": os.environ["AWS_ACCESS_KEY_ID"],"secret_access_key": os.environ["AWS_SECRET_ACCESS_KEY"],"region": "us-east-1","bucket": "acme-knowledge-base",},)
| Response field | Meaning |
|---|---|
connection_id | The integer id to use in every later call. Not a string. |
provider_id | Echoed back. |
status | Whether the credential was accepted. Branch on this, not on the HTTP status. |
account | The upstream account the credential resolved to, when the provider reports one. |
detail | Why the status is what it is. Present on a rejection. |
3. Confirm it is connected
Read the connection back and branch on status before configuring anything. A connection that exists is not necessarily usable.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)connection = client.connections.get("conn_8f21a4")if connection["status"] != "connected":print("not usable yet:", connection["status_message"], connection["error_code"])
OAuth was initiated but the callback has not arrived. Nothing will sync yet.
Authenticated. Configure it and sync.
Read status_message and error_code, then call reconnect rather than creating a second connection.
Needs a refresh. reconnect returns a fresh authorisation URL.
A user or the provider revoked access. Re-authorisation is required.
Deliberately stopped. Re-enabling is an administrative action, not a reconnect.
| Field | Meaning |
|---|---|
id | The integer connection id. |
provider_id, provider_name | Which source this connects to. |
status, status_message, error_code | Current state and why. |
external_workspace, external_account_id | The upstream workspace or account it is bound to. |
sync_enabled, sync_direction, sync_frequency | Whether and how it syncs. |
total_objects_synced | Lifetime count of objects read. |
last_sync_at, last_sync_status, next_scheduled_sync | Sync history and what is next. |
connected_by, connected_at, created_at | Provenance. |
4. List what exists
List is the operation a dashboard is built on. It returns an object with counts beside the array, so a summary needs no second call.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)result = client.connections.list(status="connected")print(result["total"], result["connected"], result["errors"])for connection in result["connections"]:print(connection["id"], connection["provider_id"], connection["status"])
| Parameter | Type | Contract |
|---|---|---|
status | string | Optional; the only filter this route accepts. One of the six connection statuses. |
| Response field | Meaning |
|---|---|
connections | The connections themselves. |
total | How many exist. |
connected | How many are healthy. |
errors | How many need attention. Drive an alert from this rather than counting client-side. |
5. Reconfigure the schedule
update changes whether a connection syncs and how often. It does not change what is selected for sync — that is the connector's own configuration page — and it cannot rename anything.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)connection = client.connections.update("conn_8f21a4",sync_enabled=True,sync_frequency="daily",)print(connection["sync_frequency"])
| Field | Accepted values |
|---|---|
sync_enabled | true or false. Turning it off stops scheduled syncs; a manual trigger still works. |
sync_frequency | Exactly one of realtime, hourly, daily, manual. Anything else is a 422. |
sync_direction | Exactly one of import, export, bidirectional. |
include_patterns, exclude_patterns | Lists of objects. Provider-specific. |
6. Repair a broken connection
When a token expires or a user revokes access, reconnect returns a fresh authorisation URL for the existing connection. Use it instead of creating a second connection: a new connection re-syncs everything from scratch and duplicates every memory the first one produced.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)result = client.connections.reconnect("conn_8f21a4")print(result["authorization_url"], result["state"])
| Response field | Meaning |
|---|---|
authorization_url | Redirect the user's browser here. Do not fetch it server-side. |
state | Identifies this attempt. |
connection_id | The existing connection being repaired — unchanged. |
7. Remove data, or remove everything
Two different endings, and choosing the wrong one is expensive:
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)# Keep the connection, delete everything it produced.result = client.connections.purge("conn_8f21a4")print(result["objects_deleted"], result["memories_deleted"])# Remove the connection and revoke the credential.client.connections.delete("conn_8f21a4")
| Response field | Meaning |
|---|---|
objects_deleted | How many synced objects were removed. |
memories_deleted | How many extracted memories were removed. |
| Purge | Delete | |
|---|---|---|
| Synced objects | Removed | Removed |
| Extracted memories | Removed | Removed |
| The connection record | Kept | Removed |
| The stored credential | Kept | Revoked |
| Next sync | Re-imports from the source | Nothing to sync |
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. |