DEV Community

Cover image for Make (인테그로마트) API 사용법
Rihpig
Rihpig

Posted on • Originally published at apidog.com

Make (인테그로마트) API 사용법

TL;DR

Make(이전 Integromat) API를 사용하면 개발자가 워크플로우 자동화, 시나리오 관리, 통합을 프로그래밍 방식으로 실행할 수 있습니다. OAuth 2.0 및 API 키 인증을 제공하며, 시나리오/실행/웹훅/팀용 RESTful 엔드포인트를 지원합니다(분당 60-600개 요청 제한). 이 가이드는 인증 설정, 시나리오 관리, 웹훅 트리거, 실행 모니터링, 프로덕션 자동화 전략의 실전 구현법을 다룹니다.

지금 Apidog을 사용해 보세요

소개

Make(Integromat)는 100개국 100만+ 사용자를 위해 매월 20억 건 이상의 작업을 처리하고 있습니다. 자동화 도구를 구축하거나, 클라이언트 워크플로우를 관리하거나, 1000+ 앱과 통합하려는 개발자라면 Make API 통합은 필수가 됩니다.

현업 에이전시의 경우 50개+ 클라이언트 자동화 관리 시, 시나리오 수동 업데이트/실행 모니터링/보고에 매주 15~25시간을 허비하게 됩니다. Make API 통합을 활용하면 시나리오 배포, 실행 추적, 오류 처리, 화이트 라벨 보고까지 자동화할 수 있습니다.

이 가이드는 Make API 통합 전체 과정을 실전 코드와 함께 안내합니다. OAuth 2.0 및 API 키 인증, 시나리오 관리, 웹훅 트리거, 실행 모니터링, 팀 관리, 프로덕션 배포 전략까지 다룹니다.

💡 Apidog: API 통합 테스트를 간소화합니다. Make 엔드포인트 테스트, OAuth 흐름 검증, 실행 응답 검사, 자동화 문제를 한 곳에서 디버깅할 수 있습니다. API 사양 가져오기, 응답 모의, 팀과 테스트 시나리오 공유도 지원합니다.

Make API란 무엇인가요?

Make는 자동화 워크플로우를 프로그래밍 방식으로 관리하기 위한 RESTful API를 제공합니다. 주요 지원 기능:

  • 시나리오 생성, 업데이트, 삭제
  • 시나리오 실행(수동 트리거)
  • 실행 기록 조회, 모니터링
  • 웹훅 관리
  • 팀 및 사용자 관리
  • 연결 및 앱 관리
  • 조직/작업 공간 설정

주요 기능

기능 설명
RESTful API JSON 기반 엔드포인트
OAuth 2.0 + API 키 유연한 인증
웹훅 실시간 실행 알림
속도 제한 요금제에 따라 분당 60-600개 요청
시나리오 관리 전체 CRUD 작업
실행 제어 실행 시작, 중지, 모니터링
팀 API 사용자 및 권한 관리

Make 요금제 및 API 접근

요금제 API 접근 속도 제한 최적의 용도
무료 제한적 60/분 테스트, 학습
Core 전체 API 120/분 소규모 기업
Pro 전체 API + 우선순위 300/분 성장하는 팀
Teams 전체 API + 관리자 600/분 에이전시, 기업
Enterprise 사용자 지정 제한 사용자 지정 대규모 조직

API 아키텍처 개요

RESTful API 구조:

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

API 버전

버전 상태 사용 사례
v2 현재 모든 새로운 통합
v1 사용 중단 예정 레거시 통합 (마이그레이션 필요)

시작하기: 인증 설정

단계 1: Make 계정 생성

  1. Make.com 방문
  2. 계정 가입
  3. 설정 > 개발자 설정 이동
  4. API 자격 증명 생성

단계 2: 인증 방법 선택

Make는 두 가지 인증 방법을 지원합니다:

방법 최적의 용도 보안 수준
API 키 내부 통합, 스크립트 높음 (안전하게 저장)
OAuth 2.0 멀티테넌트 앱, 클라이언트 통합 더 높음 (사용자 범위 토큰)

단계 3: API 키 가져오기 (간단한 방법)

내부 사용을 위한 API 키 생성:

  1. 설정 > 개발자 설정 이동
  2. API 키 생성 클릭
  3. 복사 후 안전하게 저장
# .env 파일 예시
MAKE_API_KEY="여기에_당신의_api_키"
MAKE_ORGANIZATION_ID="당신의_조직_ID"
Enter fullscreen mode Exit fullscreen mode

단계 4: OAuth 2.0 설정 (멀티테넌트 앱용)

클라이언트 통합을 위한 OAuth 설정:

  1. 설정 > 개발자 설정 > OAuth 앱 이동
  2. OAuth 앱 생성 클릭
  3. 리다이렉트 URI 구성
  4. 클라이언트 자격 증명 발급
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;

// 인증 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

단계 5: 코드를 액세스 토큰으로 교환

OAuth 콜백 처리 예시:

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
  };
};

// 콜백 라우트
app.get('/oauth/callback', async (req, res) => {
  const { code, state } = req.query;

  try {
    const tokens = await exchangeCodeForToken(code);

    // 토큰 안전 저장
    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);
    res.status(500).send('인증 실패');
  }
});
Enter fullscreen mode Exit fullscreen mode

단계 6: 인증된 API 호출 수행

재사용 가능한 API 클라이언트 예시:

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.message}`);
  }

  return response.json();
};

// 사용 예시
const scenarios = await makeRequest('/scenarios');
console.log(`발견된 시나리오 수: ${scenarios.data.length}`);
Enter fullscreen mode Exit fullscreen mode

시나리오 관리

시나리오 목록 조회

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;
};

// 사용 예시
const scenarios = await listScenarios({ limit: 100 });
scenarios.data.forEach(scenario => {
  console.log(`${scenario.name} - ${scenario.active ? '활성' : '일시 중지됨'}`);
  console.log(`  마지막 실행: ${scenario.lastRunDate || '없음'}`);
});
Enter fullscreen mode Exit fullscreen mode

시나리오 세부 정보 조회

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

// 사용 예시
const scenario = await getScenario('12345');
console.log(`이름: ${scenario.name}`);
console.log(`모듈: ${scenario.modules.length}`);
console.log(`스케줄: ${scenario.schedule?.cronExpression || '수동'}`);
Enter fullscreen mode Exit fullscreen mode

시나리오 생성

const createScenario = async (scenarioData) => {
  const scenario = {
    name: scenarioData.name,
    blueprint: scenarioData.blueprint, // 시나리오 JSON 청사진
    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;
};

// 사용 예시
const newScenario = await createScenario({
  name: '리드 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: '웹훅 리드를 Salesforce로 동기화합니다'
});

console.log(`시나리오 생성됨: ${newScenario.id}`);
Enter fullscreen mode Exit fullscreen mode

시나리오 업데이트

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

  return response;
};

// 사용 예시
await updateScenario('12345', { active: false });

await updateScenario('12345', {
  schedule: {
    cronExpression: '0 */6 * * *', // 6시간마다
    timezone: 'America/New_York'
  }
});
Enter fullscreen mode Exit fullscreen mode

시나리오 삭제

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

  console.log(`시나리오 ${scenarioId} 삭제됨`);
};
Enter fullscreen mode Exit fullscreen mode

실행 관리

시나리오 실행 트리거

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

  return response;
};

// 입력 없이 실행
const execution = await executeScenario('12345');
console.log(`실행 시작됨: ${execution.id}`);

// 입력 데이터로 실행
const executionWithData = await executeScenario('12345', {
  lead: {
    email: 'prospect@example.com',
    name: '존 도',
    company: '아크메 법인'
  }
});
Enter fullscreen mode Exit fullscreen mode

실행 기록 조회

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;
};

// 24시간 내 실패 실행 조회
const failedExecutions = await getExecutionHistory('12345', {
  from: new Date(Date.now() - 86400000).toISOString(),
  status: 'error',
  limit: 100
});

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

실행 세부 정보 조회

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

// 사용 예시
const execution = await getExecution('98765');
console.log(`상태: ${execution.status}`);
console.log(`기간: ${execution.duration}ms`);
console.log(`실행된 모듈: ${execution.modulesExecuted}`);
Enter fullscreen mode Exit fullscreen mode

실행 중단

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

  console.log(`실행 ${executionId} 중지됨`);
};
Enter fullscreen mode Exit fullscreen mode

웹훅 관리

웹훅 생성

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

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

  return response;
};

// 사용 예시
const webhook = await createWebhook({
  name: '리드 캡처 웹훅',
  scenarioId: '12345',
  type: 'custom',
  hookType: 'HEAD',
  security: { type: 'none' }
});

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

웹훅 목록 조회

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

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

웹훅 삭제

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

  console.log(`웹훅 ${webhookId} 삭제됨`);
};
Enter fullscreen mode Exit fullscreen mode

팀 및 사용자 관리

팀원 목록

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

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

팀원 추가

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;
};

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

사용자 역할 업데이트

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

  console.log(`사용자 ${userId}의 역할이 ${newRole}로 업데이트됨`);
};
Enter fullscreen mode Exit fullscreen mode

사용자 역할

역할 권한
뷰어 시나리오 보기, 편집 불가
빌더 시나리오 생성/편집
매니저 팀 관리, 결제
관리자 전체 조직 접근 권한

속도 제한

속도 제한 이해하기

요금제 분당 요청 수 버스트 제한
무료 60 100
Core 120 200
Pro 300 500
Teams 600 1000
Enterprise 사용자 지정 사용자 지정

속도 제한 헤더

헤더 설명
X-RateLimit-Limit 분당 최대 요청 수
X-RateLimit-Remaining 남은 요청 수
X-RateLimit-Reset 재설정까지 남은 시간 (초)

속도 제한 처리 구현

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(`낮은 속도 제한: ${remaining}개 남음`);
      }

      return response;
    } catch (error) {
      if (error.message.includes('429') && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`속도 제한에 걸렸습니다. ${delay}ms 후 재시도합니다...`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

프로덕션 배포 체크리스트

운영 환경 배포 전 반드시 다음을 점검하세요:

  • [ ] 내부용은 API 키, 클라이언트 통합은 OAuth 활용
  • [ ] 자격 증명 안전 저장(암호화 DB)
  • [ ] 속도 제한 및 요청 큐잉 구현
  • [ ] 실행 모니터링/알림 설정
  • [ ] 오류 알림(이메일, Slack 등) 구성
  • [ ] 실패 실행 재시도 로직 구현
  • [ ] 포괄적 로깅 추가
  • [ ] 중요한 시나리오의 백업/내보내기

실제 사용 사례

에이전시 클라이언트 관리

마케팅 에이전시가 100개+ 클라이언트 자동화를 관리할 때:

  • 과제: 클라이언트 계정별 수동 시나리오 업데이트
  • 해결책: Make API 활용 중앙 대시보드 구축
  • 결과: 70% 시간 절감, 일관 배포

핵심 구현:

  • 다중 계정 OAuth 통합
  • 대량 시나리오 배포
  • 클라이언트 사용량 보고 자동화

전자상거래 주문 처리

온라인 상점 주문 처리 자동화:

  • 과제: 창고 시스템으로 수동 주문 입력
  • 해결책: 웹훅 트리거 Make 시나리오 자동화
  • 결과: 수동 입력 제로, 99.9% 정확성

핵심 구현:

  • Shopify 웹훅 → Make 연동
  • 시나리오 기반 주문 처리 및 창고 업데이트
  • 재시도 로직 통한 오류 자동 처리

결론

Make API는 실전 자동화에 필요한 모든 기능을 제공합니다. 핵심 요약:

  • 내부는 API 키, 멀티테넌트 앱은 OAuth 2.0
  • 시나리오/실행/웹훅 전체 CRUD 지원
  • 조직 제어를 위한 팀 관리
  • 속도 제한(요금제별)
  • 프로덕션 환경에서 실행 모니터링 필수
  • Apidog는 API 테스트 및 협업을 간소화

Make API로 어떻게 인증하나요?

내부 통합은 개발자 설정에서 API 키 사용, 멀티테넌트 앱은 OAuth 2.0 사용이 권장됩니다.

시나리오를 프로그래밍 방식으로 트리거할 수 있나요?

네, /scenarios/{id}/execute 엔드포인트로 선택적 입력 데이터와 함께 수동 트리거가 가능합니다.

Make의 속도 제한은 무엇인가요?

무료는 분당 60회, Teams/Enterprise는 분당 600회 이상까지 속도 제한이 있습니다.

실행 로그를 어떻게 얻나요?

/scenarios/{id}/executions 엔드포인트로 날짜, 상태별 필터를 통한 실행 기록 조회가 가능합니다.

API를 통해 웹훅을 생성할 수 있나요?

네, /webhooks 엔드포인트로 시나리오 웹훅 생성, 목록, 삭제가 가능합니다.

Top comments (0)