Make.com Custom Apps: Create Your Own Integration Modules
Yes, you can build your own Make.com app. If the service you need isn't in Make's library of 1,000+ apps, the Custom Apps tool lets you define your own modules, map them to any REST API, handle authentication, transform data with IML, and publish the result for your team or the broader Make community. Custom apps give you full control over the API surface — something no pre-built module can match for niche or internal services.
This guide walks through the full process: from opening the Apps Editor to shipping a working custom module backed by a real API call.
What Are Make.com Custom Apps?
A custom app in Make is a user-built integration module that behaves identically to any built-in app. Once created, it appears in the Scenario builder, supports connection credentials, exposes typed input parameters, and returns structured output bundles.
Custom apps are the right tool when:
- The service you need has no Make module (niche SaaS, internal APIs, proprietary databases)
- An existing module is too limited (missing endpoints, wrong output format)
- You want to standardize API access across your team without everyone needing to understand the raw API
Custom apps are not the right tool when:
- The service already has a Make module that covers your use case
- You only need one ad-hoc call — use the HTTP module instead
- You have no API documentation for the target service
The Two Editors
Make gives you two ways to write custom apps:
| Editor | Best for |
|---|---|
| Web interface | Beginners, quick iterations, no local tooling |
| VS Code extension | Production apps, version control, team collaboration |
Both editors share the same underlying JSON config format. Start with the web interface to prototype, then migrate to VS Code for anything you'll maintain long-term.
Accessing the Web Interface
- Log in to Make.com
- Click More in the left sidebar, then Custom Apps
- Click + Create a new app
The Custom Apps dashboard shows all your private apps, their version, and publication status.
Setting Up the VS Code Extension
The VS Code extension syncs your local JSON files with Make's backend in real time.
Step 1 — Generate an API key
Navigate to your Make profile → API access → + Add token. Enable these two scopes:
sdk-apps:readsdk-apps:write
Copy the token immediately — Make only shows it once.
Step 2 — Install the extension
Search for Make Apps Editor in the VS Code Marketplace, or install Integromat.apps-sdk from the Extensions panel.
Step 3 — Connect to your organization
Open the Command Palette (Ctrl+Shift+P / Cmd+Shift+P) and run > Add SDK environment. Paste your API key and your zone URL (e.g., https://us1.make.com/api).
Your apps appear in the Make sidebar. All edits auto-upload to Make on Ctrl+S.
App Anatomy
Every Make custom app has the same five building blocks:
my-app/
├── base # Shared HTTP settings (base URL, default headers)
├── connections/ # Authentication definitions (API key, OAuth 2.0)
├── modules/ # Individual actions exposed in Scenario builder
├── rpcs/ # Remote Procedure Calls (dynamic dropdowns)
└── webhooks/ # Instant trigger endpoints
Start with connection → base → modules. RPCs and webhooks are optional unless you need dynamic UI or real-time triggers.
Step 1 — Create the App
In the web interface, click + Create a new app and fill in:
| Field | Notes |
|---|---|
| Label | Shown in Scenario builder — match the service's brand name |
| App ID | Lowercase alphanumeric, hyphen-separated (open-meteo, not OpenMeteo) — cannot be changed |
| Version | Always 1 for new apps |
| Color | Hex color for module icons (e.g., #0066cc) |
For this guide we'll build a custom app for Open-Meteo, a free weather API with no API key required.
Step 2 — Define the Connection
Even if your API is unauthenticated, Make requires a connection object. For a key-based API, the connection definition looks like this:
{
"type": "basic",
"fields": [
{
"name": "apiKey",
"type": "text",
"label": "API key",
"required": true
}
],
"validation": {
"condition": "{{connection.apiKey}}",
"throw": [
{
"message": "API key is missing."
}
]
}
}
For Open-Meteo (no auth needed), set the connection type to basic with no fields. This creates a placeholder connection so Make's module system works correctly.
OAuth 2.0 Connections
For services requiring OAuth, the connection type changes to oauth2. The required fields are:
{
"type": "oauth2",
"clientId": "{{common.clientId}}",
"clientSecret": "{{common.clientSecret}}",
"authorizeUrl": "https://api.example.com/oauth/authorize",
"tokenUrl": "https://api.example.com/oauth/token",
"scope": "read write",
"scopeSeparator": " "
}
Make handles the full PKCE flow, token refresh, and credential storage. You don't implement any of that yourself.
Step 3 — Set the Base URL
The Base section defines the root URL and any headers shared across all modules:
{
"baseUrl": "https://api.open-meteo.com/v1",
"headers": {
"Content-Type": "application/json"
}
}
All module URLs are relative to this base. If you later need to change the API domain, you update it in one place.
Step 4 — Build Your First Module
This is where the app becomes useful. Make supports five module types:
| Type | Use case | Returns |
|---|---|---|
| Action | Write, update, or delete a single record | Single bundle |
| Search | Query a list of records (with optional filters) | Multiple bundles |
| Trigger | Poll for new items on a schedule | Multiple bundles |
| Instant trigger | Receive a webhook from the service | Single bundle |
| Universal (Make an API call) | Catch-all for endpoints not covered by other modules | Raw response |
Example: Get Current Weather (Action module)
We'll create an Action module that calls GET /forecast on Open-Meteo and returns current temperature data.
In the web editor, navigate to Modules → + Add module → select Action.
The module config is split across tabs:
Communication tab
This defines the HTTP request:
{
"url": "/forecast",
"method": "GET",
"qs": {
"latitude": "{{parameters.latitude}}",
"longitude": "{{parameters.longitude}}",
"current": "temperature_2m,wind_speed_10m",
"temperature_unit": "{{parameters.unit}}"
},
"response": {
"output": "{{body}}"
}
}
{{parameters.latitude}} refers to an input parameter defined in the next tab. {{body}} maps the entire JSON response to the module's output.
Parameters tab
Input parameters are what users configure in the Scenario builder:
[
{
"name": "latitude",
"type": "number",
"label": "Latitude",
"required": true,
"help": "WGS84 coordinate between -90 and 90."
},
{
"name": "longitude",
"type": "number",
"label": "Longitude",
"required": true
},
{
"name": "unit",
"type": "select",
"label": "Temperature unit",
"required": false,
"default": "celsius",
"options": [
{ "label": "Celsius", "value": "celsius" },
{ "label": "Fahrenheit", "value": "fahrenheit" }
]
}
]
Output tab
The output tab defines the bundle structure returned that downstream modules can use:
[
{
"name": "temperature",
"type": "number",
"label": "Temperature",
"path": "current.temperature_2m"
},
{
"name": "windSpeed",
"type": "number",
"label": "Wind speed",
"path": "current.wind_speed_10m"
},
{
"name": "time",
"type": "text",
"label": "Time",
"path": "current.time"
}
]
path uses dot-notation to navigate the JSON response and pluck specific values.
Step 5 — Data Transformation with IML
IML (Integromat Markup Language) is Make's built-in expression language. You use it to transform values inside module configurations — anywhere you see {{ }} syntax.
IML gives you access to:
- Variables:
{{parameters.name}},{{body.field}},{{connection.apiKey}} - String functions:
{{toLower(parameters.name)}},{{trim(body.title)}} - Math:
{{add(parameters.qty, 1)}},{{round(body.price, 2)}} - Date/time:
{{formatDate(now, "YYYY-MM-DD")}},{{parseDate("2026-01-01", "YYYY-MM-DD")}} - Arrays:
{{first(body.results)}},{{map(body.items, "id")}} - Conditionals:
{{if(body.active, "yes", "no")}}
Practical IML example
The Open-Meteo API returns timestamps in ISO 8601 format (2026-03-15T12:00). To format them for display:
{
"name": "formattedTime",
"type": "text",
"label": "Formatted time",
"value": "{{formatDate(parseDate(body.current.time, \"YYYY-MM-DDTHH:mm\"), \"MMM D, YYYY h:mm A\")}}"
}
You can also write custom IML functions in the Functions section of your app for reusable logic across multiple modules.
Step 6 — Dynamic Dropdowns with RPCs
RPCs (Remote Procedure Calls) power dynamic select fields — dropdowns populated at runtime from an API call rather than hardcoded values.
Example: a "Project" dropdown that fetches real projects from the API when the user opens the module:
RPC definition:
{
"url": "/projects",
"method": "GET",
"response": {
"output": {
"label": "{{item.name}}",
"value": "{{item.id}}"
}
}
}
Parameter referencing the RPC:
{
"name": "projectId",
"type": "select",
"label": "Project",
"options": {
"rpc": "listProjects"
}
}
When the user opens the module, Make calls the RPC, gets the project list, and renders a live dropdown. No hardcoded option arrays needed.
Step 7 — Instant Triggers (Webhooks)
Instant triggers fire immediately when the source service pushes an event — no polling delay. Use them when the API supports webhooks.
The webhook definition registers a URL endpoint with Make and specifies how to parse the incoming payload:
{
"url": "/webhooks",
"method": "POST",
"body": {
"url": "{{webhook.url}}"
},
"response": {
"data": {
"id": "{{body.webhookId}}"
}
},
"detach": {
"url": "/webhooks/{{connection.webhookId}}",
"method": "DELETE"
}
}
Make provides the unique {{webhook.url}} — your module POSTs this to the service's webhook registration endpoint. The detach block tells Make how to unsubscribe when the user disconnects the module.
Step 8 — Test Your App
Before publishing, test each module in a live Scenario:
- In Make, open Scenarios → create a blank scenario
- Click the + icon and search for your custom app name
- Add the module, create a connection, fill in the parameters
- Click Run once and inspect the output bundles
Common errors to check:
| Error | Likely cause |
|---|---|
401 Unauthorized | Connection credentials not mapped correctly in the request headers |
400 Bad Request | A required parameter is empty or incorrectly formatted |
| Empty output | The path in the Output tab doesn't match the actual JSON response shape |
| Module not visible | App still in draft — check Custom Apps dashboard status |
Use Make's built-in log viewer (Custom Apps dashboard → Logs) to inspect raw HTTP requests and responses for each test run.
Step 9 — Publish Your App
Custom apps start as private. You have two publication paths:
Private (Team use)
Your app is available only to your Make organization. No review needed. Useful for internal APIs, proprietary systems, or apps still in development.
Public (Make Marketplace)
Submit for review by the Make team. Requirements:
- App logo (SVG, 512×512, transparent background)
- Complete module descriptions following Make's naming conventions
- All modules tested against live API
- Documentation URL
- Privacy policy and terms of service URLs
The review timeline varies — Make's documentation notes the process involves a structured review but does not publish a fixed SLA. Budget several weeks for review and any requested revisions. Make only accepts apps connecting to services not already covered by default Make apps. If a built-in Make app already covers the service, the custom app won't be approved.
To submit: Custom Apps dashboard → your app → Request review → fill in the submission form.
Full Example: Open-Meteo Weather App
Here's a complete working app configuration you can paste into the Make web editor:
Base:
{
"baseUrl": "https://api.open-meteo.com/v1"
}
Connection (no auth):
{
"type": "basic",
"fields": []
}
Module — Get current weather:
{
"communication": {
"url": "/forecast",
"method": "GET",
"qs": {
"latitude": "{{parameters.latitude}}",
"longitude": "{{parameters.longitude}}",
"current": "temperature_2m,wind_speed_10m,weather_code",
"temperature_unit": "{{parameters.unit}}"
},
"response": {
"output": "{{body}}"
}
},
"parameters": [
{
"name": "latitude",
"type": "number",
"label": "Latitude",
"required": true
},
{
"name": "longitude",
"type": "number",
"label": "Longitude",
"required": true
},
{
"name": "unit",
"type": "select",
"label": "Temperature unit",
"default": "celsius",
"options": [
{ "label": "Celsius", "value": "celsius" },
{ "label": "Fahrenheit", "value": "fahrenheit" }
]
}
],
"output": [
{
"name": "temperature",
"type": "number",
"label": "Temperature",
"path": "current.temperature_2m"
},
{
"name": "windSpeed",
"type": "number",
"label": "Wind speed (km/h)",
"path": "current.wind_speed_10m"
},
{
"name": "weatherCode",
"type": "integer",
"label": "WMO weather code",
"path": "current.weather_code"
},
{
"name": "time",
"type": "text",
"label": "Observation time",
"path": "current.time"
}
]
}
Paste the base and connection configs into the respective editors, then create one module named "Get current weather" with the communication, parameters, and output sections above. Run a test with latitude: 48.8566 (Paris) and you'll see live temperature data flowing through.
When to Use HTTP Module vs. Custom App
| Scenario | Use |
|---|---|
| One-off API call in a single scenario | HTTP module |
| Same API called in 5+ scenarios | Custom app |
| Multiple people on the team need access | Custom app |
| You want typed fields and output mapping | Custom app |
| Publishing to the marketplace | Custom app |
| API changes frequently | Reconsider — custom apps require manual updates |
The HTTP module is faster to set up but produces raw JSON output that every scenario must parse independently. A custom app absorbs that complexity once and exposes clean, mapped fields everywhere.
Custom Apps vs. Pre-Built Apify Make Integration
If your goal is to connect a web scraping workflow to Make.com without building a custom app, Apify's native Make integration is the faster path. The Apify module in Make already handles Actor runs, dataset retrieval, and webhook triggers — no custom app required.
Build a custom Make app when you control the API you're connecting to, or when no Make module exists for the service you need.
Start building on Make.com — free account available.
Yes. Make's Custom Apps tool lets any user with a Make account create their own integration modules. You define the API connection, map endpoints to module types (action, search, trigger), and configure typed parameters. The app then appears in the Scenario builder like any built-in Make app.
The Make Apps Editor is a JSON-based configuration environment available in two forms: a browser-based web editor built into Make's dashboard, and a VS Code extension (Integromat.apps-sdk) that syncs files to Make via API. Both editors support code suggestions, IML syntax highlighting, and real-time validation.
Navigate to Custom Apps in your Make dashboard, create a new app, define a connection, set a base URL, then add a module. Each module has a Communication tab (HTTP request definition), a Parameters tab (user inputs), and an Output tab (response mapping). Save, add it to a Scenario, and test with Run once.
Make custom apps support five module types: Action (single-record write/read), Search (multi-record query), Trigger (scheduled polling), Instant trigger (webhook push), and Universal/Make an API call (catch-all). The correct choice depends on whether the operation returns one or many records and whether it requires real-time or scheduled execution.
IML (Integromat Markup Language) is Make's expression language used inside custom app configurations. It lets you reference parameters ({{parameters.name}}), transform strings and numbers ({{toLower(body.title)}}), handle dates ({{formatDate(now, 'YYYY-MM-DD')}}), and write conditional logic — all within the JSON config. IML runs server-side and does not require JavaScript knowledge.
Yes, but only for services not already covered by Make's built-in app library. To publish, your app must pass Make's review process (typically 4–6 weeks), include a complete app logo, module descriptions following Make's naming conventions, and a privacy policy. Private apps require no review and are immediately available to your Make organization.
A simple action module against a documented REST API with API key auth can be working in under an hour for a developer familiar with REST concepts. An app with multiple modules, OAuth 2.0, dynamic dropdowns via RPCs, and instant trigger webhooks will take considerably longer depending on API complexity. The Make Academy offers a free course on getting started with custom apps if you're new to the process.
