DEV Community

Cover image for How to Use Make (Integromat) API ?
Wanda
Wanda

Posted on • Originally published at apidog.com

How to Use Make (Integromat) API ?

TL;DR

The Make (formerly Integromat) API lets you automate workflows, manage scenarios, and execute integrations programmatically. It supports OAuth 2.0 and API key authentication. The RESTful endpoints allow for scenario management, execution, webhooks, and team operations, with rate limits from 60-600 requests/min (by plan). This actionable guide covers authentication, scenario CRUD, webhooks, execution monitoring, and production-ready automation.

Try Apidog today


Introduction

Make (Integromat) processes over 2 billion operations monthly for 1+ million users in 100+ countries. If you're building automation tools, managing client workflows, or integrating with 1000+ apps, Make API integration is essential for scalable automation.

Agencies managing 50+ client automations often lose 15-25 hours weekly on manual scenario updates, execution monitoring, and client reporting. API integration automates deployment, execution tracking, error handling, and reporting.

This guide is a step-by-step walkthrough of Make API integration: authentication (OAuth & API key), scenario management, webhooks, monitoring, team management, and deployment strategies. You'll be able to implement a production-ready Make integration.

💡 Apidog simplifies API integration testing: Test Make endpoints, validate OAuth, inspect execution responses, and debug automations in one workspace. Import API specs, mock responses, and share tests with your team.


What Is the Make API?

The Make API enables programmatic management of automation workflows.

Core Capabilities:

  • Create, update, delete scenarios
  • Manually trigger scenario execution
  • Access execution history/logs
  • Manage webhooks
  • Manage teams, users, connections, and apps
  • Adjust organization/workspace settings

Key Features

Feature Description
RESTful API JSON-based endpoints
OAuth 2.0 + API Keys Flexible authentication
Webhooks Real-time execution notifications
Rate Limiting 60-600 requests/min by plan
Scenario Management Full CRUD operations
Execution Control Start, stop, monitor runs
Team API User and permission management

Make Plans and API Access

Plan API Access Rate Limit Best For
Free Limited 60/min Testing, learning
Core Full API 120/min Small businesses
Pro Full API + Priority 300/min Growing teams
Teams Full API + Admin 600/min Agencies, enterprises
Enterprise Custom limits Custom Large organizations

API Architecture Overview

Base URL for v2:

https://api.make.com/api/v2/
Enter fullscreen mode Exit fullscreen mode

API Versions

Version Status Use Case
v2 Current All new integrations
v1 Deprecated Legacy integrations (migrate)

Getting Started: Authentication Setup

Step 1: Create Make Account

  1. Go to Make.com
  2. Sign up for an account
  3. Navigate to Settings > Developer settings
  4. Generate API credentials

Step 2: Choose Authentication Method

Method Best For Security Level
API Key Internal scripts High (store securely)
OAuth 2.0 Multi-tenant/client apps Higher (user-scoped)

Step 3: Get API Key (Simplest Method)

Generate an API key for internal use:

  1. Go to Settings > Developer settings
  2. Click Create API key
  3. Copy and store securely
# .env file
MAKE_API_KEY="your_api_key_here"
MAKE_ORGANIZATION_ID="your_org_id"
Enter fullscreen mode Exit fullscreen mode

Step 4: Set Up OAuth 2.0 (For Multi-Tenant Apps)

Configure OAuth for client integrations:

  1. Go to Settings > Developer settings > OAuth apps
  2. Click Create OAuth app
  3. Set redirect URI
  4. Get client credentials
const MAKE_CLIENT_ID = process.env.MAKE_CLIENT_ID;
const MAKE_CLIENT_SECRET = process.env.MAKE_CLIENT_SECRET;
const MAKE_REDIRECT_URI = process.env.MAKE_REDIRECT_URI;

// Build authorization URL
const getAuthUrl = (state) => {
  const params = new URLSearchParams({
    client_id: MAKE_CLIENT_ID,
    redirect_uri: MAKE_REDIRECT_URI,
    scope: 'read write execute',
    state: state,
    response_type: 'code'
  });

  return `https://www.make.com/oauth/authorize?${params.toString()}`;
};
Enter fullscreen mode Exit fullscreen mode

Step 5: Exchange Code for Access Token

Handle the OAuth callback:

const exchangeCodeForToken = async (code) => {
  const response = await fetch('https://www.make.com/oauth/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      client_id: MAKE_CLIENT_ID,
      client_secret: MAKE_CLIENT_SECRET,
      redirect_uri: MAKE_REDIRECT_URI,
      code: code
    })
  });

  const data = await response.json();

  return {
    accessToken: data.access_token,
    refreshToken: data.refresh_token,
    expiresIn: data.expires_in
  };
};

// Handle callback
app.get('/oauth/callback', async (req, res) => {
  const { code, state } = req.query;

  try {
    const tokens = await exchangeCodeForToken(code);

    // Store tokens securely
    await db.integrations.create({
      userId: req.session.userId,
      accessToken: tokens.accessToken,
      refreshToken: tokens.refreshToken,
      tokenExpiry: Date.now() + (tokens.expiresIn * 1000)
    });

    res.redirect('/success');
  } catch (error) {
    console.error('OAuth error:', error);
    res.status(500).send('Authentication failed');
  }
});
Enter fullscreen mode Exit fullscreen mode

Step 6: Make Authenticated API Calls

Create a reusable API client:

const MAKE_BASE_URL = 'https://api.make.com/api/v2';

const makeRequest = async (endpoint, options = {}) => {
  const apiKey = options.useOAuth ? await getOAuthToken() : process.env.MAKE_API_KEY;

  const response = await fetch(`${MAKE_BASE_URL}${endpoint}`, {
    ...options,
    headers: {
      'Authorization': `Token ${apiKey}`,
      'Content-Type': 'application/json',
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Make API Error: ${error.message}`);
  }

  return response.json();
};

// Usage
const scenarios = await makeRequest('/scenarios');
console.log(`Found ${scenarios.data.length} scenarios`);
Enter fullscreen mode Exit fullscreen mode

Scenario Management

Listing Scenarios

Fetch scenarios (with filters):

const listScenarios = async (filters = {}) => {
  const params = new URLSearchParams({
    limit: filters.limit || 50,
    offset: filters.offset || 0
  });

  if (filters.folder) {
    params.append('folder', filters.folder);
  }

  const response = await makeRequest(`/scenarios?${params.toString()}`);
  return response;
};

// Usage
const scenarios = await listScenarios({ limit: 100 });
scenarios.data.forEach(scenario => {
  console.log(`${scenario.name} - ${scenario.active ? 'Active' : 'Paused'}`);
  console.log(`  Last run: ${scenario.lastRunDate || 'Never'}`);
});
Enter fullscreen mode Exit fullscreen mode

Getting Scenario Details

Fetch a single scenario:

const getScenario = async (scenarioId) => {
  const response = await makeRequest(`/scenarios/${scenarioId}`);
  return response;
};

// Usage
const scenario = await getScenario('12345');
console.log(`Name: ${scenario.name}`);
console.log(`Modules: ${scenario.modules.length}`);
console.log(`Schedule: ${scenario.schedule?.cronExpression || 'Manual'}`);
Enter fullscreen mode Exit fullscreen mode

Creating a Scenario

Create a new scenario from a blueprint:

const createScenario = async (scenarioData) => {
  const scenario = {
    name: scenarioData.name,
    blueprint: scenarioData.blueprint, // Scenario JSON blueprint
    active: scenarioData.active || false,
    priority: scenarioData.priority || 1,
    maxErrors: scenarioData.maxErrors || 3,
    autoCommit: scenarioData.autoCommit || true,
    description: scenarioData.description || ''
  };

  const response = await makeRequest('/scenarios', {
    method: 'POST',
    body: JSON.stringify(scenario)
  });

  return response;
};

// Usage
const newScenario = await createScenario({
  name: 'Lead Sync to CRM',
  blueprint: {
    modules: [
      {
        id: 1,
        app: 'webhooks',
        action: 'customWebhook',
        parameters: { /* ... */ }
      },
      {
        id: 2,
        app: 'salesforce',
        action: 'createRecord',
        parameters: { /* ... */ }
      }
    ],
    connections: [
      { from: 1, to: 2 }
    ]
  },
  active: true,
  description: 'Sync webhook leads to Salesforce'
});

console.log(`Scenario created: ${newScenario.id}`);
Enter fullscreen mode Exit fullscreen mode

Updating a Scenario

Modify scenario configuration:

const updateScenario = async (scenarioId, updates) => {
  const response = await makeRequest(`/scenarios/${scenarioId}`, {
    method: 'PATCH',
    body: JSON.stringify(updates)
  });

  return response;
};

// Usage - Pause scenario
await updateScenario('12345', { active: false });

// Usage - Update schedule
await updateScenario('12345', {
  schedule: {
    cronExpression: '0 */6 * * *', // Every 6 hours
    timezone: 'America/New_York'
  }
});
Enter fullscreen mode Exit fullscreen mode

Deleting a Scenario

Delete a scenario:

const deleteScenario = async (scenarioId) => {
  await makeRequest(`/scenarios/${scenarioId}`, {
    method: 'DELETE'
  });

  console.log(`Scenario ${scenarioId} deleted`);
};
Enter fullscreen mode Exit fullscreen mode

Execution Management

Triggering Scenario Execution

Manually run a scenario:

const executeScenario = async (scenarioId, inputData = null) => {
  const response = await makeRequest(`/scenarios/${scenarioId}/execute`, {
    method: 'POST',
    body: inputData ? JSON.stringify(inputData) : undefined
  });

  return response;
};

// Usage - Run without input
const execution = await executeScenario('12345');
console.log(`Execution started: ${execution.id}`);

// Usage - Run with input data
const executionWithData = await executeScenario('12345', {
  lead: {
    email: 'prospect@example.com',
    name: 'John Doe',
    company: 'Acme Corp'
  }
});
Enter fullscreen mode Exit fullscreen mode

Getting Execution History

Fetch execution logs:

const getExecutionHistory = async (scenarioId, filters = {}) => {
  const params = new URLSearchParams({
    limit: filters.limit || 50,
    from: filters.from,
    to: filters.to,
    status: filters.status // 'success', 'error', 'running'
  });

  const response = await makeRequest(`/scenarios/${scenarioId}/executions?${params.toString()}`);
  return response;
};

// Usage - Get failed executions from last 24h
const failedExecutions = await getExecutionHistory('12345', {
  from: new Date(Date.now() - 86400000).toISOString(),
  status: 'error',
  limit: 100
});

failedExecutions.data.forEach(exec => {
  console.log(`Execution ${exec.id}: ${exec.error?.message}`);
});
Enter fullscreen mode Exit fullscreen mode

Getting Execution Details

Fetch a single execution:

const getExecution = async (executionId) => {
  const response = await makeRequest(`/executions/${executionId}`);
  return response;
};

// Usage
const execution = await getExecution('98765');
console.log(`Status: ${execution.status}`);
console.log(`Duration: ${execution.duration}ms`);
console.log(`Modules executed: ${execution.modulesExecuted}`);
Enter fullscreen mode Exit fullscreen mode

Stopping Running Execution

Cancel an execution:

const stopExecution = async (executionId) => {
  await makeRequest(`/executions/${executionId}`, {
    method: 'DELETE'
  });

  console.log(`Execution ${executionId} stopped`);
};
Enter fullscreen mode Exit fullscreen mode

Webhook Management

Creating Webhook

Set up an incoming webhook:

const createWebhook = async (webhookData) => {
  const webhook = {
    name: webhookData.name,
    scenarioId: webhookData.scenarioId,
    type: 'custom', // 'custom' or 'raw'
    hookType: 'HEAD', // 'HEAD' or 'GET'
    security: {
      type: 'none' // 'none', 'basic', 'token'
    }
  };

  const response = await makeRequest('/webhooks', {
    method: 'POST',
    body: JSON.stringify(webhook)
  });

  return response;
};

// Usage
const webhook = await createWebhook({
  name: 'Lead Capture Webhook',
  scenarioId: '12345',
  type: 'custom',
  hookType: 'HEAD',
  security: { type: 'none' }
});

console.log(`Webhook URL: ${hook.url}`);
Enter fullscreen mode Exit fullscreen mode

Listing Webhooks

Fetch all webhooks:

const listWebhooks = async () => {
  const response = await makeRequest('/webhooks');
  return response;
};

// Usage
const webhooks = await listWebhooks();
webhooks.data.forEach(webhook => {
  console.log(`${webhook.name}: ${webhook.url}`);
});
Enter fullscreen mode Exit fullscreen mode

Deleting Webhook

Delete a webhook:

const deleteWebhook = async (webhookId) => {
  await makeRequest(`/webhooks/${webhookId}`, {
    method: 'DELETE'
  });

  console.log(`Webhook ${webhookId} deleted`);
};
Enter fullscreen mode Exit fullscreen mode

Team and User Management

Listing Team Members

Fetch users in an organization:

const listTeamMembers = async (organizationId) => {
  const response = await makeRequest(`/organizations/${organizationId}/users`);
  return response;
};

// Usage
const members = await listTeamMembers('org-123');
members.data.forEach(member => {
  console.log(`${member.email} - ${member.role}`);
});
Enter fullscreen mode Exit fullscreen mode

Adding Team Member

Invite a user to the organization:

const addTeamMember = async (organizationId, email, role) => {
  const response = await makeRequest(`/organizations/${organizationId}/users`, {
    method: 'POST',
    body: JSON.stringify({
      email: email,
      role: role // 'viewer', 'builder', 'manager', 'admin'
    })
  });

  return response;
};

// Usage
await addTeamMember('org-123', 'newuser@example.com', 'builder');
Enter fullscreen mode Exit fullscreen mode

Updating User Role

Change user permissions:

const updateUserRole = async (organizationId, userId, newRole) => {
  await makeRequest(`/organizations/${organizationId}/users/${userId}`, {
    method: 'PATCH',
    body: JSON.stringify({ role: newRole })
  });

  console.log(`User ${userId} role updated to ${newRole}`);
};
Enter fullscreen mode Exit fullscreen mode

User Roles

Role Permissions
Viewer View scenarios, no edits
Builder Create/edit scenarios
Manager Manage team, billing
Admin Full organization access

Rate Limiting

Understanding Rate Limits

Plan Requests/Minute Burst Limit
Free 60 100
Core 120 200
Pro 300 500
Teams 600 1000
Enterprise Custom Custom

Rate Limit Headers

Header Description
X-RateLimit-Limit Max requests per minute
X-RateLimit-Remaining Remaining requests
X-RateLimit-Reset Seconds until reset

Implementing Rate Limit Handling

Example for exponential backoff on 429:

const makeRateLimitedRequest = async (endpoint, options = {}, maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await makeRequest(endpoint, options);

      const remaining = response.headers.get('X-RateLimit-Remaining');
      if (remaining < 10) {
        console.warn(`Low rate limit: ${remaining} remaining`);
      }

      return response;
    } catch (error) {
      if (error.message.includes('429') && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Rate limited. Retrying in ${delay}ms...`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

Production Deployment Checklist

Before going live, ensure:

  • [ ] Use API keys for internal, OAuth for client integrations
  • [ ] Store credentials securely (encrypted database)
  • [ ] Implement rate limiting and request queuing
  • [ ] Set up execution monitoring and alerting
  • [ ] Configure error notifications (email, Slack)
  • [ ] Implement retry logic for failed executions
  • [ ] Add comprehensive logging
  • [ ] Backup/export critical scenarios

Real-World Use Cases

Agency Client Management

A marketing agency automates 100+ client accounts.

Implementation Steps:

  • Multi-account OAuth integration
  • Bulk scenario deployment via API
  • Automated client usage reporting

Outcome: 70% time savings and consistent deployments.

E-commerce Order Processing

An online store automates order fulfillment.

Implementation Steps:

  • Shopify webhook triggers Make scenario
  • Scenario processes order and updates warehouse system
  • Error handling with retry logic

Outcome: No manual entry, 99.9% accuracy.


Conclusion

The Make API offers robust workflow automation. To implement effectively:

  • Use API key for internal, OAuth 2.0 for multi-tenant apps
  • Manage scenarios, executions, webhooks programmatically
  • Use team management for organization control
  • Respect rate limits (60-600 requests/min, plan-based)
  • Monitor executions in production
  • Apidog streamlines API testing and collaboration (learn more)

How do I authenticate with Make API?

Use API key from Developer settings for internal integrations, or OAuth 2.0 for multi-tenant applications.

Can I trigger scenarios programmatically?

Yes. Use the /scenarios/{id}/execute endpoint to run scenarios manually with optional input data.

What are Make rate limits?

Rate limits range from 60 requests/minute (Free) to 600 requests/minute (Teams/Enterprise).

How do I get execution logs?

Use /scenarios/{id}/executions to fetch execution history, filterable by date and status.

Can I create webhooks via API?

Yes. Use /webhooks endpoint to create, list, and delete webhooks for scenarios.

Top comments (0)