Skip to main content
doc0blade47/mem0documentation home
Sign in

Zapier Integration

Last updated Oct 11, 2026100% grounded
Relevant source files

The following files were used as context for generating this wiki page:

Overview

The Zapier Integration package provides native Zapier workflow automation nodes for Mem0, built on the zapier-platform-core library. It enables seamless integration between external applications and Mem0's memory backend by exposing core actions and searches such as adding new memories, searching semantically, retrieving lists of user memories, and deleting outdated or incorrect memory entries.

Sources: integrations/zapier-mem0/src/index.ts:1-31

Application Architecture and Package Registration

Core Binding and Package Exports

The Zapier integration packages its entire application structure as an exported CommonJS module object bound to zapier-platform-core. The integration imports version as platformVersion directly from zapier-platform-core and pairs it with the application version read dynamically from package.json.

import { version as platformVersion } from 'zapier-platform-core';
import authentication from './authentication';
import { includeApiKey, handleBadResponses } from './middleware';
import addMemory from './creates/add_memory';
import deleteMemory from './creates/delete_memory';
import searchMemories from './searches/search_memories';
import getMemories from './searches/get_memories';
import pkg from '../package.json';
 
const app = {
	version: pkg.version,
	platformVersion,

Sources: integrations/zapier-mem0/src/index.ts:1-12

The main app configuration object aggregates request interceptors, response handlers, authentication definitions, and operational modules under explicit dictionary keys. Creates and searches are dynamically keyed using the .key property exported by each individual action module.

	authentication,
 
	beforeRequest: [includeApiKey],
	afterResponse: [handleBadResponses],
 
	creates: {
		[addMemory.key]: addMemory,
		[deleteMemory.key]: deleteMemory,
	},
 
	searches: {
		[searchMemories.key]: searchMemories,
		[getMemories.key]: getMemories,
	},
 
	resources: {},
	triggers: {},
};
 
export = app;

Sources: integrations/zapier-mem0/src/index.ts:14-33

Note

The resources and triggers collections are initialized as empty objects in the core application definition, meaning the integration relies entirely on explicit creates and searches rather than polling triggers or dynamic resource descriptors.

Sources: integrations/zapier-mem0/src/index.ts:29-30

Application Component Mapping

The application configuration wires together authentication modules, request/response middleware functions, and four primary workflow operations split equally between creates and searches.

Component CategoryTarget PropertyMapped Module / IdentifierSource File Reference
Platform VersionplatformVersionzapier-platform-core version exportintegrations/zapier-mem0/src/index.ts:1-1
App Versionversionpackage.json version field (pkg.version)integrations/zapier-mem0/src/index.ts:8-11
Authenticationauthentication./authentication moduleintegrations/zapier-mem0/src/index.ts:2-14
Request MiddlewarebeforeRequest[includeApiKey]integrations/zapier-mem0/src/index.ts:3-16
Response MiddlewareafterResponse[handleBadResponses]integrations/zapier-mem0/src/index.ts:3-17
Create Actioncreates[addMemory.key]./creates/add_memoryintegrations/zapier-mem0/src/index.ts:4-20
Create Actioncreates[deleteMemory.key]./creates/delete_memoryintegrations/zapier-mem0/src/index.ts:5-21
Search Operationsearches[searchMemories.key]./searches/search_memoriesintegrations/zapier-mem0/src/index.ts:6-25
Search Operationsearches[getMemories.key]./searches/get_memoriesintegrations/zapier-mem0/src/index.ts:7-26

Sources: integrations/zapier-mem0/src/index.ts:1-33

API Key Authentication Handshake

Authentication Configuration and Test

The integration implements custom API key authentication where credentials are submitted with the header format Authorization: Token <apiKey>, matching the convention used across Mem0's SDKs. Connection verification is performed by the test function executing a GET request against the /v1/ping/ endpoint.

// Custom (API key) authentication for Mem0.
// The key is sent as "Authorization: Token <apiKey>" (matches Mem0's SDKs).
const test = (z: ZObject, _bundle: Bundle) => z.request({ url: '/v1/ping/', method: 'GET' });
 
export default {
	type: 'custom',
	test,

Sources: integrations/zapier-mem0/src/authentication.ts:3-9

The authentication schema defines two configuration fields: apiKey and baseUrl. The apiKey field uses a password type so the Zapier platform masks the secret in the connection UI, and it specifies a default help text directing users to retrieve keys starting with m0- from the dashboard. The baseUrl field is optional, defaults to https://api.mem0.ai, and permits overriding for self-hosted or non-default deployments.

fields: [
	{
		key: 'apiKey',
		label: 'Mem0 API Key',
		// `password` so Zapier masks the key in the connection UI (it is a secret).
		type: 'password',
		required: true,
		helpText:
			'Your Mem0 API key (starts with `m0-`). Create one at [app.mem0.ai](https://app.mem0.ai) → Settings → API Keys.',
	},
	{
		key: 'baseUrl',
		label: 'Base URL',
		type: 'string',
		required: false,
		default: 'https://api.mem0.ai',
		helpText: 'Override only for self-hosted or non-default deployments.',
	},
],

Sources: integrations/zapier-mem0/src/authentication.ts:10-28

Tip

The connectionLabel property is explicitly set to {{user_email}}, which extracts the account email directly from the /v1/ping/ test response to let users distinguish between multiple configured Mem0 accounts inside the Zap editor.

Sources: integrations/zapier-mem0/src/authentication.ts:29-33

Field Definition Reference

Field KeyLabelTypeRequiredDefault ValueDescription / Help Text
apiKeyMem0 API KeypasswordtrueNoneMem0 API key starting with m0-, obtainable at app.mem0.ai under Settings → API Keys
baseUrlBase URLstringfalsehttps://api.mem0.aiOverride URL for self-hosted or non-default deployments

Sources: integrations/zapier-mem0/src/authentication.ts:10-28

HTTP Middleware and Request Interception

Request Interception and Bearer Token Injection

The includeApiKey request middleware operates as a beforeRequest interceptor, processing every outbound request object before transmission. When bundle.authData.apiKey is present, it initializes or mutates request.headers and applies the authorization token using the Token <apiKey> format. If request.url begins with a forward slash (/), the middleware resolves it against the configured base URL, defaulting to https://api.mem0.ai if bundle.authData.baseUrl is omitted or empty, and strips any trailing slashes from the base URL string.

export const includeApiKey = (
	request: MutableRequest,
	_z: ZObject,
	bundle: Bundle,
): MutableRequest => {
	if (bundle.authData && bundle.authData.apiKey) {
		request.headers = request.headers || {};
		request.headers.Authorization = `Token ${bundle.authData.apiKey}`;
	}
	// Resolve relative URLs against the configured base URL.
	if (request.url && request.url.startsWith('/')) {
		const base = (bundle.authData && bundle.authData.baseUrl) || 'https://api.mem0.ai';
		request.url = `${base.replace(/\/$/, '')}${request.url}`;
	}
	return request;
};

Sources: integrations/zapier-mem0/src/middleware.ts:4-19

Warning

Because Zapier's z.request client does not throw exceptions on non-2xx HTTP status codes by default, omitting or bypassing response interception causes server errors (4xx and 5xx responses) to flow downstream as fake successes, turning empty search results or error payloads into incorrectly created memory records.

Sources: integrations/zapier-mem0/src/middleware.ts:21-23

Response Parsing and Error Handling

The handleBadResponses middleware functions as an afterResponse interceptor, evaluating status codes on incoming ZResponse objects. It explicitly catches HTTP 401 Unauthorized and 403 Forbidden responses, throwing a Zapier AuthenticationError with the message 'The Mem0 API key you supplied is invalid or lacks access.'. For any response status of 400 or greater, it extracts error details from response.data or falls back to response.content and 'unknown error'.

export const handleBadResponses = (
	response: ZResponse,
	z: ZObject,
	_bundle: Bundle,
): ZResponse => {
	if (response.status === 401 || response.status === 403) {
		throw new z.errors.Error(
			'The Mem0 API key you supplied is invalid or lacks access.',
			'AuthenticationError',
			response.status,
		);
	}
	if (response.status >= 400) {
		const data = (response.data as Record<string, unknown>) || {};
		const raw =
			data.detail || data.error || data.message || response.content || 'unknown error';
		// DRF sometimes returns detail as an object/array; stringify so the
		// thrown message never renders as "[object Object]".
		const detail = typeof raw === 'string' ? raw : JSON.stringify(raw);
		throw new z.errors.Error(
			`Mem0 API request failed (HTTP ${response.status}): ${detail}`,
			'Mem0ApiError',
			response.status,
		);
	}
	return response;
};

Sources: integrations/zapier-mem0/src/middleware.ts:24-48

Note

Django Rest Framework (DRF) frequently returns error details as structured objects or arrays rather than plain strings. The response parser checks whether the raw detail value is a string, and if not, serializes it via JSON.stringify to prevent thrown error messages from rendering as [object Object].

Sources: integrations/zapier-mem0/src/middleware.ts:38-47

Memory Creation Action and Polling

Execution Flow and Input Processing

The add_memory create operation collects input fields and submits them to the Mem0 API. Boolean inputs such as infer and waitForCompletion arrive from Zapier as strings ('true' or 'false') and undergo explicit string comparison coercion to preserve user selections. The request body constructs a messages array using bundle.inputData.role (defaulting to 'user') and bundle.inputData.content, tagging the source attribution as 'ZAPIER'. Optional scope identifiers (user_id, agent_id, run_id) and extraction controls (custom_instructions, includes, excludes) are appended when provided. Metadata and custom categories accept either raw objects or JSON-encoded strings, throwing an InvalidInput error with a 400 status if parsing fails.

const perform = async (z: ZObject, bundle: Bundle): Promise<AddResponse | EventResponse> => {
	// Zapier boolean fields can arrive as the strings 'true'/'false'; coerce
	// explicitly so "Infer = No" / "Wait = No" are honored.
	const infer = String(bundle.inputData.infer) !== 'false';
	// Waiting is opt-in (the poll path can exceed Zapier's step timeout).
	const wait = String(bundle.inputData.waitForCompletion) === 'true';
 
	const body: Record<string, unknown> = {
		messages: [{ role: bundle.inputData.role || 'user', content: bundle.inputData.content }],
		infer,
		// Attribution is recorded server-side by Mem0 from this source tag.
		source: 'ZAPIER',
	};
	if (bundle.inputData.user_id) body.user_id = bundle.inputData.user_id;
	if (bundle.inputData.agent_id) body.agent_id = bundle.inputData.agent_id;
	if (bundle.inputData.run_id) body.run_id = bundle.inputData.run_id;
	if (bundle.inputData.metadata) {
		try {
			body.metadata =
				typeof bundle.inputData.metadata === 'string'
					? JSON.parse(bundle.inputData.metadata)
					: bundle.inputData.metadata;
		} catch {
			throw new z.errors.Error('Metadata must be valid JSON.', 'InvalidInput', 400);
		}
	}
	// Custom extraction controls (optional): steer what the API extracts.
	if (bundle.inputData.custom_instructions) {
		body.custom_instructions = bundle.inputData.custom_instructions;
	}
	if (bundle.inputData.custom_categories) {
		try {
			body.custom_categories =
				typeof bundle.inputData.custom_categories === 'string'
					? JSON.parse(bundle.inputData.custom_categories)
					: bundle.inputData.custom_categories;
		} catch {
			throw new z.errors.Error('Custom Categories must be valid JSON.', 'InvalidInput', 400);
		}
	}
	if (bundle.inputData.includes) body.includes = bundle.inputData.includes;
	if (bundle.inputData.excludes) body.excludes = bundle.inputData.excludes;
 

Sources: integrations/zapier-mem0/src/creates/add_memory.ts:30-72

Warning

Zapier requires at least one entity ID scope. While user_id is marked required in the input field definitions, omitting entity scopes or supplying malformed JSON string inputs for metadata or custom_categories triggers an immediate validation exception before network dispatch.

Sources: integrations/zapier-mem0/src/creates/add_memory.ts:52-54, integrations/zapier-mem0/src/creates/add_memory.ts:117-117

Asynchronous Event Polling

When waitForCompletion is enabled (true), the execution handler checks whether the initial POST /v3/memories/add/ response returned an event_id with an unresolved status (PENDING or RUNNING). If so, it invokes pollEvent, which queries GET /v1/event/{eventId}/ across a bounded retry budget.

const pollEvent = async (z: ZObject, eventId: string): Promise<EventResponse> => {
	for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {
		const res = await z.request({ url: `/v1/event/${eventId}/`, method: 'GET' });
		const data = res.data as EventResponse;
		const status = data && data.status;
		if (status === 'SUCCEEDED') {
			return data;
		}
		if (status === 'FAILED') {
			const reason = (data && (data.error || data.message)) || 'unknown error';
			throw new z.errors.Error(`Mem0 memory event ${eventId} failed: ${reason}`, 'Mem0EventFailed', 400);
		}
		await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
	}
	throw new z.errors.Error(
		`Timed out waiting for memory event ${eventId}. The add was accepted and is ` +
			`likely still completing on the server — a timeout here does not mean it failed.`,
		'Mem0Timeout',
		408,
	);
};

Sources: integrations/zapier-mem0/src/creates/add_memory.ts:8-28

ConstantValueDescription / Purpose
POLL_INTERVAL_MS1500Delay in milliseconds between consecutive status check requests during event polling
MAX_POLL_ATTEMPTS40Maximum number of poll attempts, bounding the total poll budget to 60 seconds under Zapier's per-step execution timeout

Sources: integrations/zapier-mem0/src/creates/add_memory.ts:3-5

Note

If polling exhausts all 40 attempts without reaching a terminal status, the function throws a Mem0Timeout error (HTTP 408). This indicates that memory addition was accepted and is still processing server-side; a timeout here does not mean the operation failed.

Sources: integrations/zapier-mem0/src/creates/add_memory.ts:22-27

Memory Deletion Action Execution

Operation Handling and Identifier Validation

The delete_memory create definition exposes a Zapier integration action that targets individual memory records for removal. Its operation object exports a single perform function which accepts the core Zapier context object z and the bundle payload. Input validation is enforced at the field definition layer, where the memory_id input field is explicitly designated as a required string.

export default {
	key: 'delete_memory',
	noun: 'Memory',
	display: {
		label: 'Delete Memory',
		description: 'Deletes a memory by its ID.',
	},
	operation: {
		perform,
		inputFields: [{ key: 'memory_id', label: 'Memory ID', type: 'string', required: true }],
		sample: { message: 'Memory deleted successfully' },
	},
};

Sources: integrations/zapier-mem0/src/creates/delete_memory.ts:12-24

Caution

Deleting a memory is a destructive and irreversible operation. Once the delete request reaches the upstream backend, the memory record and its embedded vector states are permanently removed from the user store.

Sources: integrations/zapier-mem0/src/creates/delete_memory.ts:12-18

Request Execution and Status Reporting

The perform handler constructs an HTTP DELETE request targeting the Mem0 endpoint. To prevent URL malformation, the memory identifier extracted from bundle.inputData.memory_id is passed through String() casting and encodeURIComponent() encoding before interpolation into the path string /v1/memories/${encodeURIComponent(String(bundle.inputData.memory_id))}/.

const perform = async (z: ZObject, bundle: Bundle) => {
	// Trailing slash required (Django APPEND_SLASH); id encoded so a stray slash can't mistarget the path.
	const response = await z.request({
		url: `/v1/memories/${encodeURIComponent(String(bundle.inputData.memory_id))}/`,
		method: 'DELETE',
	});
	return response.data || { message: 'Deleted', memory_id: bundle.inputData.memory_id };
};

Sources: integrations/zapier-mem0/src/creates/delete_memory.ts:3-10

Note

A trailing slash is explicitly required on the request URL to accommodate Django's APPEND_SLASH routing configuration. Furthermore, encoding the identifier guarantees that stray slash characters within a malformed ID cannot mistarget the URL path hierarchy.

Sources: integrations/zapier-mem0/src/creates/delete_memory.ts:4-8

Upon receiving a successful response from the server, the handler returns response.data if present. If the API response body is empty or lacks data, it falls back to a default status object containing a success message and the target identifier: { message: 'Deleted', memory_id: bundle.inputData.memory_id }.

return response.data || { message: 'Deleted', memory_id: bundle.inputData.memory_id };

Sources: integrations/zapier-mem0/src/creates/delete_memory.ts:9-9

Search and Retrieval Operations

Semantic Query Searching

The search functionality in the Zapier integration exposes a dedicated search module that queries stored memories using natural language semantics. The perform function constructs a POST request body containing the search query, an explicit output_format set to 'v1.1', and a top_k parameter calculated by clamping the user-supplied limit input to a minimum of 1 with a default ceiling of 50. If a user_id is provided in bundle.inputData, it is nested within a filters object.

const perform = async (z: ZObject, bundle: Bundle): Promise<Memory[]> => {
	const body: Record<string, unknown> = {
		query: bundle.inputData.query,
		output_format: 'v1.1',
		top_k: Math.max(1, Math.floor(Number(bundle.inputData.limit) || 50)),
	};
	if (bundle.inputData.user_id) body.filters = { user_id: bundle.inputData.user_id };
 

Sources: integrations/zapier-mem0/src/searches/search_memories.ts:3-10

The search request is dispatched against the endpoint /v3/memories/search/. To ensure robust output handling across varying payload structures, the response data is guarded against null or empty bodies by checking if it is an array or an object containing a results property.

	const response = await z.request({
		url: '/v3/memories/search/',
		method: 'POST',
		body,
	});
	// Searches must return an array; guard against a null/empty body.
	const data = response.data as Memory[] | { results?: Memory[] } | null;
	return Array.isArray(data) ? data : data?.results ?? [];
};

Sources: integrations/zapier-mem0/src/searches/search_memories.ts:11-19

Note

The search module defines its schema with three input fields: query (string, required), user_id (string, required), and limit (integer, defaulting to 50). All searches enforce user-level scoping via filters when the identifier is present.

Sources: integrations/zapier-mem0/src/searches/search_memories.ts:30-34

Filter Extraction and Memory Listing

Memory listing operations are managed through the get_memories search definition, which retrieves all stored memories for a specific user. The execution handler dynamically builds an optional filter object containing the user_id when supplied in the bundle input data.

const perform = async (z: ZObject, bundle: Bundle): Promise<Memory[]> => {
	const body: Record<string, unknown> = {};
	if (bundle.inputData.user_id) body.filters = { user_id: bundle.inputData.user_id };
 

Sources: integrations/zapier-mem0/src/searches/get_memories.ts:3-6

Pagination parameters are passed via URL query parameters, utilizing Math.max(1, Math.floor(...)) to sanitize both page and limit values. The limit field maps to page_size with a default of 50, whereas page defaults to 1. The request is sent as a POST payload to /v3/memories/.

const response = await z.request({
	url: '/v3/memories/',
	method: 'POST',
	params: {
		page: Math.max(1, Math.floor(Number(bundle.inputData.page) || 1)),
		page_size: Math.max(1, Math.floor(Number(bundle.inputData.limit) || 50)),
	},
	body,
});

Sources: integrations/zapier-mem0/src/searches/get_memories.ts:7-15

Tip

Both search and listing modules incorporate identical result-normalization guards. If the upstream server returns a response object wrapped in a results property rather than a raw array, the parser automatically unwraps it or falls back to an empty array to prevent downstream execution halts.

Sources: integrations/zapier-mem0/src/searches/get_memories.ts:16-18

Was this page helpful?