TL;DR
Make(이전 Integromat) API를 사용하면 개발자가 워크플로우 자동화, 시나리오 관리, 통합을 프로그래밍 방식으로 실행할 수 있습니다. OAuth 2.0 및 API 키 인증을 제공하며, 시나리오/실행/웹훅/팀용 RESTful 엔드포인트를 지원합니다(분당 60-600개 요청 제한). 이 가이드는 인증 설정, 시나리오 관리, 웹훅 트리거, 실행 모니터링, 프로덕션 자동화 전략의 실전 구현법을 다룹니다.
소개
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/
API 버전
| 버전 | 상태 | 사용 사례 |
|---|---|---|
| v2 | 현재 | 모든 새로운 통합 |
| v1 | 사용 중단 예정 | 레거시 통합 (마이그레이션 필요) |
시작하기: 인증 설정
단계 1: Make 계정 생성
- Make.com 방문
- 계정 가입
- 설정 > 개발자 설정 이동
- API 자격 증명 생성
단계 2: 인증 방법 선택
Make는 두 가지 인증 방법을 지원합니다:
| 방법 | 최적의 용도 | 보안 수준 |
|---|---|---|
| API 키 | 내부 통합, 스크립트 | 높음 (안전하게 저장) |
| OAuth 2.0 | 멀티테넌트 앱, 클라이언트 통합 | 더 높음 (사용자 범위 토큰) |
단계 3: API 키 가져오기 (간단한 방법)
내부 사용을 위한 API 키 생성:
- 설정 > 개발자 설정 이동
- API 키 생성 클릭
- 복사 후 안전하게 저장
# .env 파일 예시
MAKE_API_KEY="여기에_당신의_api_키"
MAKE_ORGANIZATION_ID="당신의_조직_ID"
단계 4: OAuth 2.0 설정 (멀티테넌트 앱용)
클라이언트 통합을 위한 OAuth 설정:
- 설정 > 개발자 설정 > OAuth 앱 이동
- OAuth 앱 생성 클릭
- 리다이렉트 URI 구성
- 클라이언트 자격 증명 발급
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()}`;
};
단계 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('인증 실패');
}
});
단계 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}`);
시나리오 관리
시나리오 목록 조회
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 || '없음'}`);
});
시나리오 세부 정보 조회
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 || '수동'}`);
시나리오 생성
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}`);
시나리오 업데이트
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'
}
});
시나리오 삭제
const deleteScenario = async (scenarioId) => {
await makeRequest(`/scenarios/${scenarioId}`, {
method: 'DELETE'
});
console.log(`시나리오 ${scenarioId} 삭제됨`);
};
실행 관리
시나리오 실행 트리거
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: '아크메 법인'
}
});
실행 기록 조회
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}`);
});
실행 세부 정보 조회
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}`);
실행 중단
const stopExecution = async (executionId) => {
await makeRequest(`/executions/${executionId}`, {
method: 'DELETE'
});
console.log(`실행 ${executionId} 중지됨`);
};
웹훅 관리
웹훅 생성
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}`);
웹훅 목록 조회
const listWebhooks = async () => {
const response = await makeRequest('/webhooks');
return response;
};
// 사용 예시
const webhooks = await listWebhooks();
webhooks.data.forEach(webhook => {
console.log(`${webhook.name}: ${webhook.url}`);
});
웹훅 삭제
const deleteWebhook = async (webhookId) => {
await makeRequest(`/webhooks/${webhookId}`, {
method: 'DELETE'
});
console.log(`웹훅 ${webhookId} 삭제됨`);
};
팀 및 사용자 관리
팀원 목록
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}`);
});
팀원 추가
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');
사용자 역할 업데이트
const updateUserRole = async (organizationId, userId, newRole) => {
await makeRequest(`/organizations/${organizationId}/users/${userId}`, {
method: 'PATCH',
body: JSON.stringify({ role: newRole })
});
console.log(`사용자 ${userId}의 역할이 ${newRole}로 업데이트됨`);
};
사용자 역할
| 역할 | 권한 |
|---|---|
| 뷰어 | 시나리오 보기, 편집 불가 |
| 빌더 | 시나리오 생성/편집 |
| 매니저 | 팀 관리, 결제 |
| 관리자 | 전체 조직 접근 권한 |
속도 제한
속도 제한 이해하기
| 요금제 | 분당 요청 수 | 버스트 제한 |
|---|---|---|
| 무료 | 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;
}
}
}
};
프로덕션 배포 체크리스트
운영 환경 배포 전 반드시 다음을 점검하세요:
- [ ] 내부용은 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)