teachyou.ai academy
← All posts
Workflow AutomationMakeOpenAINo-CodeIntegrations

Building an OpenAI Scenario in Make

Pramod Dutta · Jun 28, 2026 · 16 min read

If you search for "make openai" you are usually trying to do one of two things: connect an OpenAI account inside Make so a scenario can call GPT models, or figure out why a scenario you already built keeps failing on malformed JSON. This guide covers both. We will build a Make OpenAI scenario from a blank canvas, wire up the connection correctly, map prompts safely, parse the response, add retries, and then extend it with structured outputs and raw HTTP calls for anything the native module does not expose. Everything below assumes you have a Make account (any tier that allows external app connections) and an OpenAI API key with billing enabled.

What "Make OpenAI" Integration Actually Means

Make is a visual automation platform: you drag modules onto a canvas, connect them with lines, and each module either triggers a scenario, transforms data, or calls an external API. The OpenAI app inside Make is a thin, opinionated wrapper around OpenAI's REST API. It exposes modules like "Create a Chat Completion," "Create a Completion," "Create an Image," "Create a Transcription," and "Create a Moderation," each mapped to a specific OpenAI endpoint with a form-based UI instead of raw JSON.

The tradeoff is speed versus flexibility. The native module gets you from zero to a working GPT call in under two minutes. The moment you need something the form does not expose (a new model parameter, a beta header, streaming, or an endpoint OpenAI shipped last month that Make has not wrapped yet) you drop down to Make's generic HTTP module and call the OpenAI REST API directly with a JSON body. Most real Make OpenAI scenarios end up using both: the native module for the common case, HTTP for the edge cases.

Setting Up the Make OpenAI Connection

Before you can use any OpenAI module, you need a connection.

  1. In OpenAI's dashboard, create an API key scoped to a project (not your personal default key) so you can track usage and revoke it independently later.
  2. In Make, add any OpenAI module to a new scenario (search "OpenAI" in the module picker).
  3. Click "Add" next to the Connection field.
  4. Paste the API key. Make does not ask for an organization ID unless you use multiple OpenAI orgs; leave it blank otherwise.
  5. Name the connection something specific, like openai-teachyou-prod, not the default OpenAI connection. You will thank yourself later when a scenario has three connections and you need to know which key is burning budget.

A note on key hygiene: Make stores the key encrypted on its side, but anyone with edit access to the scenario can technically select the module and see which connection it uses (not the raw key itself). If you are building scenarios that other teammates will edit, use a key with a hard spending cap set in OpenAI's usage limits page, and rotate it if you ever remove someone's access to the Make organization.

Anatomy of a Make OpenAI Scenario

A working scenario is five parts, in order:

  1. Trigger: something that starts the run (a webhook, a new row in Google Sheets, a new email in Gmail, a schedule).
  2. Preprocessing: clean or reshape the incoming data before it hits OpenAI (trim whitespace, truncate long text, pull a field out of nested JSON).
  3. OpenAI call: the Create a Chat Completion module (or HTTP equivalent).
  4. Postprocessing: parse the response, extract the text, optionally parse JSON the model returned.
  5. Output: write the result somewhere (a database, a spreadsheet row, a Slack message, an email reply).

Build in that order and test after every step using Make's "Run once" button, which lets you inspect the exact input and output bundle at each module. This is the single biggest productivity unlock in Make: you are never debugging blind, you are looking at the actual JSON that flowed through each node.

Step 1: Choose Your Trigger

For a first scenario, use the Webhooks app's "Custom webhook" trigger. It gives you a URL you can hit with curl during development, which is faster to iterate on than waiting for a spreadsheet row to appear.

  1. Add a Webhooks > Custom webhook module.
  2. Click "Add" to create a new webhook, name it, and copy the generated URL.
  3. Determine the data structure by sending one sample request:
curl -X POST https://hook.make.com/your-webhook-id \
  -H "Content-Type: application/json" \
  -d '{"ticket_id": "1042", "message": "My export keeps timing out after 30 seconds"}'

Make inspects the payload and automatically builds a data structure from it, so every field (ticket_id, message) becomes a mappable variable in the next module. If you skip this step, later modules will not offer those fields as mapping options.

Step 2: Add the OpenAI Module and Map the Prompt

Add a second module: OpenAI > Create a Chat Completion.

Fill in:

  • Model: pick from the dropdown, or type a model name directly if Make's list has not caught up with a newer release.
  • Messages: this is the important part. Add a System message and a User message as separate rows.

- System: You are a support triage assistant. Classify the ticket and reply with strict JSON only. - User: map the webhook's message field directly into this box by clicking it and selecting the variable from the panel on the right, rather than typing it as plain text.

  • Max tokens: set a hard ceiling (for example 300) so a runaway response cannot silently balloon your bill.
  • Temperature: for classification or extraction tasks, set this low (0 to 0.2). Save higher values for creative writing scenarios.

Mapping matters more than it looks. If you type {{1.message}} by hand instead of clicking the variable in the picker, a typo in the module number breaks the mapping silently, and you will not notice until the bundle comes back empty. Always use the picker.

Step 3: Parse and Route the Response

The Create a Chat Completion module returns a bundle with fields like choices[].message.content, usage.total_tokens, and id. The text you actually want is usually choices[1].message.content (Make arrays are 1-indexed, not 0-indexed, which trips up anyone coming from JavaScript or Python).

If you asked the model for JSON, add a JSON > Parse JSON module next, pointing it at the completion text. This turns the string into a real Make data structure, so downstream modules can reference .category, .priority, .summary, or whatever fields you asked the model to return, instead of you having to regex a string.

Then add a Router module if the result needs to branch (for example, route high-priority tickets to a Slack alert and everything else to a Google Sheets log). Each route out of a Router gets its own filter, set by clicking the wrench icon on the connecting line and adding a condition like priority equals high.

Step 4: Add Error Handling and Retries

OpenAI calls fail for reasons that have nothing to do with your logic: rate limits, transient 500s, a model returning malformed JSON when you asked for strict JSON. Do not skip this step; it is the difference between a scenario that runs quietly for months and one that pages you at 2am.

Right-click the OpenAI module and choose "Add error handler." Inside the error handler branch, add:

  • A Retry directive on the OpenAI module itself (right-click, "Add error handler" gives you the option, or configure it directly on the module's error settings) with 2 to 3 attempts and an increasing interval, to absorb transient rate limit or network errors.
  • A Resume or Ignore directive further down the chain for non-critical failures, so one bad run does not halt the entire scenario's execution history.
  • For the JSON parse step specifically, wrap it with its own error handler that falls back to a "manual review" branch (write the raw text to a spreadsheet with a needs_review flag) rather than letting a malformed response crash the scenario. Models occasionally add a stray sentence before the JSON even when instructed not to; treat that as an expected failure mode, not an edge case.

Make's scenario settings also have a global "Sequential processing" toggle and a "Maximum number of cycles" limit. For anything calling OpenAI, keep sequential processing on unless you have explicitly designed for concurrent API calls, since parallel execution multiplies your risk of hitting rate limits simultaneously.

Structured Outputs and Function Calling in Make

Asking the model to "reply with JSON only" in the system prompt works most of the time, but it is not guaranteed. OpenAI's structured outputs and function calling features constrain the model to a schema at the API level, which is far more reliable.

The native Create a Chat Completion module in Make exposes a "Response Format" field. Set it to JSON mode and, if the module version supports it, paste a JSON schema directly. A typical schema for the ticket triage example:

{
  "type": "json_schema",
  "json_schema": {
    "name": "ticket_triage",
    "schema": {
      "type": "object",
      "properties": {
        "category": {"type": "string", "enum": ["billing", "bug", "feature_request", "other"]},
        "priority": {"type": "string", "enum": ["low", "medium", "high"]},
        "summary": {"type": "string"}
      },
      "required": ["category", "priority", "summary"],
      "additionalProperties": false
    },
    "strict": true
  }
}

If your version of the native module does not expose a schema field, use the HTTP module instead (covered next) and pass this object as response_format in the request body directly. Either way, once the schema is enforced, you can drop the defensive "manual review" branch's retry count, because malformed JSON becomes rare rather than occasional.

For tool-style function calling (letting the model decide to call a "lookup_order" or "create_refund" function), define the tools array the same way in the request body, then parse the tool_calls array in the response and route each call to the corresponding Make module (an HTTP request to your backend, a database lookup module, and so on) using a Router.

Calling Any OpenAI Endpoint with the HTTP Module

Anything OpenAI supports that the native Make module has not wrapped yet (a new model flag, the Responses API, batch endpoints, or file uploads for fine-tuning) is reachable through Make's generic HTTP > Make a request module.

  1. URL: https://api.openai.com/v1/chat/completions (swap the path for whichever endpoint you need).
  2. Method: POST.
  3. Headers: add Authorization with value Bearer followed by your API key, and Content-Type set to application/json. Store the key in a Make Data Store or a Custom Variable rather than pasting it in plaintext inside the module if multiple people edit the scenario.
  4. Body type: Raw, Content type JSON.
  5. Request content:
{
  "model": "gpt-4.1",
  "messages": [
    {"role": "system", "content": "You are a support triage assistant."},
    {"role": "user", "content": "{{1.message}}"}
  ],
  "temperature": 0,
  "max_tokens": 300
}

The HTTP module gives you the raw response body as a string, so chain a JSON > Parse JSON module right after it to turn it back into mappable fields, exactly as you would with the native module's output. The tradeoff for this flexibility is that Make cannot validate the request shape for you ahead of time; a typo in a field name returns an OpenAI error rather than a Make-side warning, so test with "Run once" before scheduling.

Real Scenario: Support Ticket Triage

Putting the pieces together, a full support triage scenario looks like this:

  1. Webhooks > Custom webhook receives {ticket_id, message, customer_email} from your helpdesk tool.
  2. OpenAI > Create a Chat Completion classifies the ticket using the structured output schema above.
  3. JSON > Parse JSON turns the completion text into category, priority, summary.
  4. Router splits on priority:

- high goes to Slack > Create a Message, posting to a #support-urgent channel with the ticket ID and summary. - everything else goes to Google Sheets > Add a Row, logging ticket_id, category, priority, summary, and a timestamp.

  1. Both branches converge on a final HTTP module that patches your helpdesk ticket with the computed category and priority via its own API, closing the loop.

This scenario typically runs in under three seconds end to end for a short ticket, and the entire cost is one chat completion call per ticket, which at low temperature and a small max token cap stays cheap even at a few thousand tickets a month.

Real Scenario: Content Repurposing Pipeline

A second common pattern: turn one long-form asset into several shorter ones automatically.

  1. Google Drive > Watch Files triggers when a new transcript document lands in a folder.
  2. Google Docs > Get a Document pulls the full text.
  3. A Tools > Set Variable module truncates or chunks the text if it exceeds a safe token budget for your chosen model.
  4. OpenAI > Create a Chat Completion runs once per output format you need (a LinkedIn post, a Twitter thread, a newsletter blurb), each with its own system prompt describing the target format and voice.
  5. An Iterator module (Flow Control > Iterator) loops if you generate multiple thread posts as an array, feeding each item to a downstream Twitter or Buffer module.
  6. An Aggregator module (Flow Control > Aggregator) can collect all outputs back into a single digest email if you want one summary of everything generated in the run.

Because each format is its own OpenAI module call, you can tune temperature and system prompt independently per format (a Twitter thread wants punch and brevity; a newsletter blurb wants a calmer, longer register), and if one format's call fails, the Router and error handler pattern from earlier keeps the other formats running.

Controlling Cost and Rate Limits

Three habits keep a Make OpenAI scenario from becoming an expensive surprise:

  • Set `max_tokens` explicitly on every completion module. Leaving it unset means the model can generate up to its context limit, and a single malformed prompt loop (rare, but it happens with function calling chains) can burn through budget fast.
  • Cache repeated prompts where possible. If a scenario calls OpenAI with the same system prompt and similar user inputs repeatedly (for example, categorizing the same handful of recurring ticket types), consider a Data Store lookup before the OpenAI module: check if you have already classified an identical message, and skip the API call if so.
  • Watch Make's own operation count, not just OpenAI's token usage. Make bills by "operations," and every module execution (including the JSON parse, the Router, the error handler) counts as one. A scenario with five modules processing one item consumes five operations, not one. For high-volume scenarios, consolidate steps where you reasonably can, and use Make's built-in execution history to spot which module is running more often than expected (usually a sign of an unintended loop or a trigger firing on updates as well as creates).

Set a hard usage alert in OpenAI's billing dashboard and a scenario-level "Maximum number of cycles" cap in Make as two independent circuit breakers. Neither one alone is a safety net if the other misconfigures.

Testing, Scheduling, and Versioning

Before turning a scenario live:

  1. Use "Run once" on the full chain with at least three different sample inputs, including one deliberately malformed one (empty message, missing field), to confirm your error handlers actually catch what you expect.
  2. Check the "Data usage" tab on each module after a test run to see real token counts and response times, not estimates.
  3. Set the scheduling. For webhook-triggered scenarios, there is no schedule to set, the webhook fires on demand. For polling triggers (Google Sheets, Gmail, Airtable), Make's minimum interval depends on your plan tier; pick the loosest interval that still meets your latency needs; polling every minute for a workflow that only needs hourly freshness wastes operations.
  4. Before editing a live scenario, duplicate it first (right-click the scenario in the list, "Clone"). Edit the clone, test it thoroughly, then swap the webhook URL or trigger source over once you are confident, rather than editing the production scenario in place. This gives you an instant rollback if the new version misbehaves.
  5. Turn scenario logging on ("History" tab shows every run with input/output bundles) and check it weekly for the first month a scenario is live. Most Make OpenAI failures are quiet ones: a field that stopped being mapped correctly after an upstream app changed its output shape, not a loud crash.

FAQ

Does Make support every OpenAI model? Make's dropdown list of models lags behind OpenAI's release cadence by anywhere from days to a few weeks. If a model you want is missing from the dropdown, type its exact API name into the field manually, or switch to the HTTP module and pass the model name directly in the JSON body.

Can I stream responses in a Make scenario? Make's native OpenAI module returns a completed response, not a token stream, because Make scenarios operate on discrete bundles rather than an open connection. If you need streaming behavior for an end-user chat interface, build that piece outside Make (a small backend service) and have Make handle the surrounding automation instead.

Why does my JSON parsing step keep failing even with a system prompt asking for JSON only? A plain instruction in the system prompt is a request, not a guarantee. Switch to the response_format structured output schema shown earlier, either through the native module's Response Format field or the raw HTTP request body. That constrains the model at the API level and removes almost all malformed-output failures.

How do I keep my OpenAI API key safe when multiple teammates edit the same Make scenario? Use a connection stored once at the organization level rather than pasted per module, restrict who has edit access to the scenario in Make's team settings, and set a hard spending cap on the key itself in OpenAI's dashboard so a mistake anywhere in the scenario has a ceiling.

Is it cheaper to use the native OpenAI module or the HTTP module? Neither costs more in OpenAI token pricing since both hit the same API. The difference is in Make's own operation count: the native module and the HTTP module each consume one operation per call, so cost is identical there too. Choose based on flexibility, not price: native module for standard chat completions, HTTP module when you need a field or endpoint the native module does not expose.

What is the fastest way to debug a scenario that fails intermittently? Open the scenario's History tab, find a failed run, and click into it to see the exact input and output bundle at each module for that specific execution. Intermittent failures are almost always either a rate limit (visible as a 429 status in the OpenAI module's error output) or a shape change in upstream data (a field that was present in your test payload but missing in a real one). The bundle inspector tells you which within seconds, faster than guessing from the error message alone.