Skip to content

Every 10 minutes

Reply to quote requests with prices from your Supabase products

Quote requests in your inbox get a reply priced from your Supabase product table, and every quote is logged.

Runs
Every 10 minutes
Apps
Gmail, Supabase
AI
Yes, uses the built-in AI allowance
Access
Gmail send+read; Supabase read+write

Send this to your assistant

Create a ClickRuntime automation: every 10 minutes, find new quote-request emails, work out the products and quantities with AI, look up prices in my Supabase products table, save the quote as a Gmail draft reply and log it in my quotes table.

Paste it into your assistant. It tells you what it will send or change before it runs live.

First time? Adding ClickRuntime to your assistant takes about two minutes.

Why use it

Why teams use this automation

A wholesaler gets quote requests by email all day: '200 of the blue mugs and 50 totes, what's the price?'. Each one means checking the price list, doing the maths and writing it up. Slow quotes lose orders to faster competitors.

Reading the request, pricing it from your own product table and preparing the reply cuts the turnaround from hours to minutes, while you still check each quote before it's sent.

What you get out of it

  • Quote in minutes

    Speed often decides who wins the order. A ready reply lets you answer while the buyer is still comparing.

  • Prices always current

    Quotes use the prices in your product table, not an old PDF price list.

  • Fewer maths mistakes

    Line totals and the grand total are calculated, not typed.

  • Every quote logged

    The quotes table records what was offered, to whom and when, ready for follow-up.

How it works

What happens, step by step

  1. Every 10 minutes, ClickRuntime checks your sales inbox for new emails.

  2. AI decides whether each is a quote request and lists the products and quantities asked for.

  3. It looks up each product's price in your Supabase products table and calculates the totals.

  4. It saves a reply with the quote as a Gmail draft in the same thread and logs the quote in your quotes table.

  5. Unknown products are flagged in Slack, and handled emails are remembered.

Before it runs live

  • Connect Google through your own Google app (a one-time, 10-minute setup), so it works with your own Gmail
  • Connect Supabase

What you get

RunsEvery 10 minutes
Reply to quote requests with prices from your Supabase productstoday, 9:00Succeeded
Gmail · DraftsRe: Price for mugs – Northwind Mug: 200 x 4.20 = 840.00 · Acme Tote: 50 x 6.50 = 325.00 · Total: 1,165.00

Build your own

Need it to work differently?

This template is a starting point. Copy the prompt and change it, or describe a different automation from scratch, with your own conditions, more apps or an AI step. Your assistant writes it, tests it and runs it on ClickRuntime.
  • Your own rules

    Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.

  • Any number of apps

    One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.

  • AI where it helps

    Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.

  • On a schedule or on each event

    Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.

Changes you can ask for

  • Act only on the items that match your own rules, and skip the rest
  • Change what the AI looks for, or how it writes the result
  • Add another app, for example also send it to Slack
  • Combine it with other Gmail and Supabase steps into one automation

Under the hood

The code that runs this automation

This is the Python script that runs each time the automation starts. Your AI assistant writes it for you when you send the prompt, and you allow each step in your assistant. To change how the automation works, describe the change to your assistant and it updates the script for you. For every function it can use, see the script reference.
generate_quotes_from_inbound_requests.pyexample
import base64
from email.message import EmailMessage
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from clickruntime import on_trigger, credentials, http, state, notify, ai, report_fetched
SUPABASE = "https://your-project.supabase.co/rest/v1"

def sb(method, path, **kw):
    key = credentials.secret("SUPABASE_KEY")
    r = http.request(method, f"{SUPABASE}/{path}", **kw, headers={"apikey": key, "Authorization": f"Bearer {key}", "Prefer": "return=representation,resolution=merge-duplicates"})
    return r.raise_for_status() or (r.json() if r.content else None)

SCHEMA = {"type": "object", "properties": {"is_quote": {"type": "boolean"}, "items": {"type": "array", "items": {"type": "object",
          "properties": {"product": {"type": "string"}, "qty": {"type": "integer"}}}}}}

@on_trigger
def run(event):
    gmail, done = build("gmail", "v1", credentials=Credentials(credentials.connection("google", "work")), cache_discovery=False), set(state.get("done") or [])
    msgs = [m for m in gmail.users().messages().list(userId="me", q="to:sales@northwind.com newer_than:1d").execute().get("messages", []) if m["id"] not in done]
    report_fetched(len(msgs))
    if not msgs:
        return {"summary": "Nothing new"}
    prices = {p["name"].lower(): p["price"] for p in sb("GET", "products?select=name,price")}
    for m in msgs:
        full = gmail.users().messages().get(userId="me", id=m["id"]).execute()
        h, done = {x["name"]: x["value"] for x in full["payload"]["headers"]}, done | {m["id"]}
        req = ai.generate(f"Is this a quote request? List products and quantities.\n{full['snippet']}", json_schema=SCHEMA, max_output_tokens=200).json
        if not req["is_quote"]:
            continue
        lines = [(i["product"], i["qty"], prices.get(i["product"].lower())) for i in req["items"]]
        total = sum(q * p for _, q, p in lines if p)
        body = "\n".join(f"{n}: {q} x {p:.2f} = {q * p:,.2f}" if p else f"{n}: {q} – price on request" for n, q, p in lines)
        msg = EmailMessage()
        msg["To"], msg["Subject"] = h["From"], "Re: " + h.get("Subject", "Your quote")
        msg.set_content(f"Thanks for your request. Here's your quote:\n\n{body}\n\nTotal: {total:,.2f}")
        gmail.users().drafts().create(userId="me", body={"message": {"threadId": full["threadId"], "raw": base64.urlsafe_b64encode(msg.as_bytes()).decode()}}).execute()
        sb("POST", "quotes", json={"email": h["From"], "total": total, "lines": body, "message_id": m["id"]})
        if any(p is None for *_, p in lines):
            notify.slack(f"Quote for {h['From']} has unpriced items", channel="#sales")
    state.set("done", list(done)[-1000:])
    return {"emails": len(msgs)}

FAQ

Common questions

Is the quote sent automatically?
It's saved as a draft reply so you can check it. Ask for it to be sent directly once you trust the results.
What if a product isn't in my table?
That line is marked 'price on request' and a note is posted to Slack so someone can price it.
How does it know an email is a quote request?
AI classifies each new email in your sales inbox. Only requests for prices or quotes are handled.
What permissions does it need?
Gmail send+read; Supabase read+write. Nothing else in your accounts is used.
Does it need AI?
Yes. It uses ClickRuntime's built-in AI, so you don't need an OpenAI or Anthropic key. Every plan includes a monthly AI allowance.
How many runs does it use?
One run each time it checks. Checks that find nothing new and stop right away aren't counted.
Can I change how it works?
Yes. Describe the change to your AI assistant, for example a different schedule, channel or filter. It updates the automation, tests it and tells you what changed.

Set up “Reply to quote requests with prices from your Supabase products” from your assistant

Copy the prompt above, or connect your assistant first. Free plan, no credit card.