The Zapier alternative, written in Python.
Zapier connects two apps in ten minutes. Once an automation grows branches, loops and judgment calls, a Task is a program instead of a step list.
invoices = qbash.integrations.xero.list_invoices(status="AUTHORISED")["data"]["Invoices"] for invoice in invoices: match = qbash.ai.run_prompt( slug="match-invoices", variables={"invoice": invoice}, ) if match["confidence"] < 0.8: qbash.integrations.slack.create_message(channel="#finance", text=match["note"])
Model and provider agnostic.
Anthropic
OpenAI
Gemini
xAI
OpenRouterAmazon
PerplexityMoonshotAI
MetaQwen
qbash vs Zapier
Zapier has the largest catalogue in the category and the best cold start in it. These rows are about what happens after an automation stops being simple.
| Feature | qbash | Zapier |
|---|---|---|
| What you build | A Python program | A Zap: a trigger and ordered steps |
| Billable unit | The run, plus the model calls your code makes | The task, and every step counts |
| Adding a step | Costs nothing | Costs more per run |
| Branching and looping | Language features | Paths and looping steps, each billed |
| Large batches | concurrency and max_per_minute are arguments | Awkward past modest volumes |
| Long runs | Up to 12 hours | Short step timeouts |
| Change history | A revision on every save, with a line-level diff | Zap version history |
| Tests | A tests.py rides with the task, in the same revision | Not included |
| Model output | An output schema constrains the model to your JSON | Not constrained |
| Prompts | Owned by a Task, versioned with it, and called by slug | Prompt text sits in the step |
| Retrying a partial run | Checkpoints skip the items that finished | Replay the run |
| Shared team credentials | Yes, brokered server-side, shared with chat | Yes, spanning Zaps and Chatbots |
| Run surface for non-developers | Typed inputs render a form | Interfaces and Forms |
| Building without code | The builder drafts the task as code you edit | Copilot builds a Zap |
| Integrations | 45+ integrations, 390+ operations, plus raw HTTP | Thousands of apps |
| Time to a first automation | Minutes, if you write Python | Minutes, for anyone |
It’s code.
Loops, branches, and functions, + models where needed. Your code owns the orchestration: what runs, in what order, and when. Reviewable, versioned, and diffable, so a team maintains and improves it like any software.
Logic that outgrew a step list
Paths inside paths are hard to follow and harder to change safely. The same logic in Python is a few conditionals you read in one screen and review as a diff before it ships.
for invoice in invoices: if invoice["total"] > 10_000: route = "manual-review" elif match["confidence"] > 0.9: route = "auto-post" else: route = "queue"
Predictable token spend
A prompt is only used when you call it, so you decide when to spend tokens. A task is one run whether it executes ten lines or ten thousand, and cached lookups and checkpoints stop a retry paying twice.
rate = qbash.cache.get_or_set("fx-rate", fetch_rate, ttl="6h") result = qbash.parallel( reconcile, invoices, concurrency=8, checkpoint="march-close", )
A test harness
A tests.py rides with the task, versioned in the same revision as the code. Assert the whole flow end to end, and run it from the editor to catch a break before it ships. Tests run in a sandbox, so an unmocked integration or model call raises instead of reaching a live Slack channel.
def test_low_confidence_goes_to_queue(): out = reconcile(FIXTURE) assert out["route"] == "queue"
How Zapier pricing counts tasks.
Zapier bills per successful action, so the bill tracks how many actions a Zap takes multiplied by how often it fires. A six-action Zap firing a thousand times a month is six thousand tasks. Zapier and Make grow with the complexity of an automation. n8n grows with how often it runs.
Plan limits and task allowances change, so these rows describe the billable unit without quoting figures. Check zapier.com for current numbers before deciding.
| Zapier | Make | n8n Cloud | qbash | |
|---|---|---|---|---|
| Billable unit | Task, per successful action | Credit, per module call | Workflow execution | Run, plus model calls |
| Trigger firing | Free | One credit, whatever it returns | Counts as the execution | Counts as the run |
| Adding a step | More per run | More per run | Nothing | Nothing |
| Doubling frequency | Doubles | Doubles | Doubles | Doubles the model calls |
| Iterating 1,000 rows | Roughly 1,000 tasks | Roughly 1,000 credits | Depends on loop shape | One run |
| Filters and branching | Free | Branch modules still count | Nothing | Nothing, it is an if statement |
| Cost known before deploy | Calculable, steps times runs | Calculable, modules times runs | Roughly | Yes, calls sit in the code |
- Triggers never count, however often the plan polls for them.
- Filter and Paths steps are free, and a Zap stopped by a filter has run no actions, so it costs nothing.
- Formatter, Delay, Looping, Digest, Storage, Tables and Forms steps are free.
- A step that fails or is skipped is not billed, since nothing was sent.
- Sub-Zaps bill for the call and the return on top of the actions inside them.
- Replaying a run recounts every step it repeats.
- A filter placed after an action has already paid for the records it discards. Move it above the action and the cheap step decides first.
Python in Zapier runs inside one Code step.
Code by Zapier runs Python or JavaScript inside one step of a Zap, with a short timeout and a restricted set of packages. The script inside the step is portable. The Zap logic around it is what has to be rebuilt when you move it into a Task.
| Capability | What it does | Where it stops |
|---|---|---|
| Python support | Runs Python or JavaScript inside a Zap step | Requests and a small set of built-in modules, with no pip install |
| Billing | Available on all paid Zapier plans | Each code step execution counts as a task. Loops multiply the count |
| Timeout | Code runs between Zap steps | Short runtime limit. Rules out batch processing or long API sequences |
| Code reuse | Code lives inside one step | Cannot call functions from another step. Logic duplicates across the Zap |
| Testing | Test individual Zap steps | No assertion framework to run before going live |
ChatGPT in Zapier runs through AI by Zapier.
You add an AI by Zapier step, pick a provider and model, and its usage comes out of your task count, so there is no separate OpenAI bill unless you connect your own key. The older ChatGPT (OpenAI) app still exists for teams that bring an OpenAI key.
| Capability | What it does | Where it stops |
|---|---|---|
| Adding AI to a Zap | Analyze, summarize, or generate text inside a Zap step | Advanced or Premium models count as 3 or 5 tasks per run. A trigger plus two actions running 100 times a day is 6,000 tasks a month on a Standard model |
| Model output | Output fields you define by name and type, or generate from the prompt | Anything that branches on the result still needs Paths or extra steps |
| Model choice | OpenAI, Anthropic, Google Gemini, Azure OpenAI, or Amazon Bedrock, chosen per step | Logic that picks a model per input, or retries on a different one, has to be built out of more steps |
| Prompt management | Written in the step configuration | A prompt used in several Zaps is copied into each one, so a change means editing every Zap |
| Running from ChatGPT | Zapier MCP lets ChatGPT call Zapier actions | Per-task billing applies to every action fired |
- Each prompt picks its own model from OpenAI, Anthropic, Gemini, Grok and OpenRouter.
- An output_schema constrains the model to your JSON, so the branch that follows is an if statement in the same script.
- Connect qbash as an MCP server in ChatGPT, Claude Code or Cursor, and every shared Task becomes a tool the model can call.
- Behind that call is one run, however many model calls and branches the script makes.
stubs = qbash.integrations.gmail.search_messages( query="is:unread label:support", max_results=50, )["messages"] for stub in stubs: email = qbash.integrations.gmail.get_email(email_id=stub["id"])["email"] triage = qbash.ai.run_prompt( slug="triage-support", variables={"subject": email["subject"], "body": email["body"]}, ) if triage["needs_response"]: draft = qbash.ai.run_prompt( slug="draft-response", variables={"email": email, "category": triage["category"]}, ) qbash.integrations.slack.create_message( channel="#support-drafts", text=f"Re: {email['subject']}\n\n{draft['response']}", )
Moving a Zap across.
Most teams should not move everything. Zapier is good at the simple connections, so move the automations that got expensive or fragile and leave the rest.
- Pick the Zap with the most steps or the highest monthly task count.
- Describe it to the builder and it drafts the task as code your developer edits. Python from a Code step carries over as it is.
- Connect the accounts once at the org level, rather than per step.
- Run both in parallel, then move the trigger over.
Where Zapier fits better.
Zapier earned its position, and there are cases where nothing here improves on it.
- You need an app from the long tail of thousands, with no usable public API.
- Nobody on the team writes code.
- The automation is genuinely two steps and will stay that way.
- Non-technical colleagues need to build their own automations, not run yours.
Questions
Is qbash cheaper than Zapier?
It depends on shape, not volume alone. Zapier bills per task, so a ten-step run costs ten times a one-step run. A task is a single run however many lines it executes, which is why the gap widens as automations get more complex rather than just more frequent.
Can qbash replace Zapier completely?
For most teams it should not. Zapier is very good at simple two-app connections and its catalogue is far larger. The automations worth moving are the ones that grew branches, process batches, or call models.
What is the best Zapier alternative for developers?
It depends what you want to own. For a canvas you can self-host, n8n or Activepieces. For durable execution as a library inside your own application, Temporal, Inngest or Trigger.dev. qbash fits when you want the automation to be code but do not want to run the infrastructure under it.
Do non-technical teammates lose access if we move off Zapier?
No. A task declares typed inputs and those render as a form, so a colleague runs it with their own parameters and never sees the code. Results can land in Slack or as a chat they ask follow-up questions in.
What counts as a task in Zapier?
A task is a successful action step, meaning something the Zap sent to another app. Triggers and utility steps such as Filter, Formatter and Delay are free, and so is a step that fails or is skipped. Check zapier.com for current allowances, since plans change.
Why is my Zapier task count higher than expected?
Usually a Zap takes more actions per run, or fires more often, than you remember. Loops turn one run into hundreds of actions, and replays and Sub-Zaps add counts of their own. Counting actions per run and multiplying by trigger volume normally explains the gap.
Is Make cheaper than Zapier?
Often, on the per-unit price, because Make charges a credit per module call and prices those credits lower. Both bill per thing your automation does, so both grow with complexity. Make also charges a credit for the trigger where Zapier does not, and modules inside each active branch count, so a scenario with routers and iterators can consume faster than its step count suggests.
Can Zapier's Code step run any Python package?
No. Only requests and the bundled modules are available, so logic that needs pandas or another package has to be rewritten or moved to an external service.
How much does Zapier with ChatGPT cost at scale?
An AI by Zapier step on a Standard model counts as 1 task per run, and Advanced or Premium models count as 3 or 5. A Zap with a trigger and two actions running 100 times a day uses 6,000 tasks a month on a Standard model, or 12,000 if the AI step uses an Advanced model.
Can I trigger a Zap from ChatGPT?
Yes, via Zapier MCP. ChatGPT can call Zapier actions in natural language. qbash offers the same through its own MCP server, which exposes Tasks, memory folders and selected connector tools to the client.
Is there a free plan?
Yes. The Free plan includes scheduled runs, 3 Tasks and 100 executions a month, with no credit card. Paid plans start at $37 a month.
Competitor details reviewed . Vendors change plans and features without notice, so check theirs before deciding.
More comparisons
Ship your first task.
Open the editor, write a script against your connected accounts, and put it on a trigger. Or describe it, and the builder drafts the task as code you edit.