Skip to main content

Quote and approve work requests

Scope a job, send the client a price, get their approval, log the hours you spend, and invoice it — without leaving the workspace.

Before you start

  • The workspace must already have at least one client. If nobody holds the workspace-client role, there is nobody to approve a quote and nobody to invoice. See Invite a client to a workspace.
  • To set a price or see costs you need to be an account owner or admin. Account members can do everything else — create requests, move work along, log hours, comment, attach files — but pricing and margin are closed to them.
  • To send an invoice you also need Stripe Connect set up for the agency, and the client_billing feature on your plan.

A work request is one scoped job: a title, a description, an optional estimate, and a price. It carries its own conversation, its own attachments, and its own record of the hours you spent on it.

The lifecycle

A request moves through a fixed set of states, and each move belongs to one side:

You seeThe client seesWhat it meansWho moves it
DraftnothingBeing scoped. Not visible to the client at all.Agency
Needs estimateAwaiting estimateSomebody asked for work and it has no quote yet.Client (or agency)
Awaiting clientAwaiting your approvalYou've sent a price. The ball is in their court.Agency prices it
Approved / DeclinedsameThe client accepted or rejected the quote.Client only
In progress → Delivered → ClosedsameThe work itself.Agency
CancelledCancelledThe job is off. It can't be reopened.Agency

The two columns differ on purpose. The same state is named from each side's point of view, so a status never tells a customer to approve their own quote.

Two rules are worth committing to memory:

  • Only the client can approve. There is no agency button that accepts a quote on their behalf, at any permission level. That is deliberate — an approval is the client's commercial consent.
  • A draft is invisible. Nothing about a request reaches the client until it leaves draft, including its attachments. Use drafts freely to scope work privately.

To cancel a request, open its detail page and click Cancel request. It's offered in every state except Draft, Delivered, Closed and Cancelled, and it asks you to confirm first: a cancelled request can't be reopened, and no new time can be logged on it (a timer already running on it still records its time when stopped). The client sees it as Cancelled in their portal and isn't emailed. A draft isn't offered the button, since cancelling it would make it visible to the client.

Step 1: Create the request

  1. Open the queue

    Switch into the client's workspace and go to Clients → Work Requests, or visit /[workspaceSlug]/workspace/work-requests.

  2. Add a request

    Give it a title the client will recognise on an invoice and a description of what's in scope. Both are visible to the client once the request leaves draft, so write the description for them, not for your team.

Clients can also start one themselves from Work requests → New request in their portal. Theirs arrives as Submitted with just a title, description, and any files they attached — they can't set a price or an estimate.

Step 2: Price it

Open the request and fill in the estimate. Pick a basis:

  • Fixed — you name a price, and that's what the client is billed.
  • Hourly — you set a rate, and the bill is the rate times the hours worked after the client approves, up to the estimated total.
  • Retainer — the work is covered by an existing arrangement. Retainers are never turned into one-off invoices.

You also choose when it becomes billable: at approval, or on delivery. Delivery is the default and is the safer choice for anything open-ended — the request only becomes invoiceable once you've actually finished it.

Saving and sending are separate:

  • Save draft keeps the price as an unsent draft. The client can't see it and isn't told. The card shows Unsent changes until you send or discard it.
  • Send to client publishes the price, moves the request to Awaiting client, and notifies the workspace's clients. The toast tells you how many were notified — or that nobody was, if the workspace has no client yet.

The first line of the estimate card always says what the client can currently see.

Changing or withdrawing a price

Until the client approves, you can still change the price:

  • Edit it and Save draft to work on a revision. The client keeps seeing the price you last sent until you click Send update, which notifies them that the estimate changed and asks them to approve again.
  • Withdraw estimate takes a sent price back. The client is told it was withdrawn, the request returns to Needs estimate, and your terms are kept as an unsent draft so you can revise and send again.
  • Discard draft deletes unsent changes.

A client's approval always applies to the version they were looking at. If you send an update while they have the old one open, their approval is refused and their page refreshes to show the new terms. Once a request is approved, its terms are fixed — they're shown as Agreed terms and can no longer be edited.

Pricing is owner and admin only

Account members don't see the price field, the margin panel, or the invoice button — the server omits that data from their response entirely, rather than hiding it in the interface. If a teammate reports the estimate form missing, check their account role.

Step 3: The client decides

The client sees the request in their portal at Work requests, with the description, the price, and the estimated hours. They can approve it, decline it with a reason, or ask a question in the comments first.

What they never see: your logged hours, your costs, your margin, or any comment you marked internal.

Step 4: Do the work and log hours

Move the request to In progress, then Delivered when it's done.

Log hours as you go from the request's detail page, on any request that hasn't been cancelled. That includes time spent scoping and estimating before the client approves. Each entry takes a start and end time and an optional note. Hours matter for two reasons: on an hourly request, the ones that started after approval are what the client is billed, and on every request they're what the margin panel measures your profit against.

Time that started before the client approved is marked Before approval in the time log. It counts toward your costs, but it's never billed, even on an hourly request.

See all logged time

Two pages list time entries across requests, and both are named Time:

  • In a client's workspace, open Time in the sidebar's client group to see only that client's time. Filter it by request, person and date range. Log time here always files the entry on one of this client's requests.
  • At the agency level, open Time to see every client's time together, plus internal time that isn't attached to any request. This page adds a client filter.

Owners and admins see everyone's entries on both pages. Members see only their own. You can also press ⌘K (Ctrl+K on Windows and Linux) and type "time" to jump to the Time page for wherever you are.

The margin panel shows your logged hours (and how many of them were before approval), your effective hourly rate across all of them, and — when the request is linked to a workflow — what that workflow's AI runs actually cost. If no workflow is linked it says so rather than showing a zero, because "we didn't measure this" and "this was free" are different facts.

Step 5: Invoice it

Once the request passes its billable moment (approval or delivery, whichever you chose), an Invoicing card appears on the detail page. Click Generate invoice and confirm to create the invoice in your connected Stripe account, with the request's title as the line item. The confirmation restates the price before the invoice is created (on an hourly request, the rate and cap), and on an hourly request it also reminds you that the logged hours become final and can no longer be edited. The invoice appears in the client's portal under Billing, and the client's billing contact gets an email with a link to it.

On an hourly request, the invoice covers time that started after the client approved. If there aren't any yet, you'll see Nothing to invoice yet and no invoice is created. Log the work, then generate it again.

The button is safe to click twice. Every invoice is keyed to the request itself, so a double-click, a lost connection, or a retry all land on the same invoice — you cannot accidentally bill a client twice for one job.

Retainers aren't invoiced here

A retainer is a recurring arrangement, not a one-off charge, so no invoice button appears on one. Bill it through the client's subscription instead.

Comments: internal versus client-visible

Every request has one thread with two kinds of comment.

  • Internal — your team only. This is the default for anything you write.
  • Client-visible — shown in the client's portal, and they can reply.

Clients can only ever write client-visible comments; there is no way for them to author an internal note, and no way for them to read one. If you're discussing scope, cost, or whether to push back on a request, internal is where that belongs.

Ordering the queue

The queue is in manual priority order — drag a request to move it. The order is the agency's own; clients see their requests in their own view and never see your prioritisation.

See every client's requests at once

To see what all your clients have asked for without opening each workspace, go to Work Requests in the agency sidebar, just below Clients.

  • Requests from every client are listed newest first, with the client's name on each row.
  • Use the All clients picker to narrow the list to one client.
  • Click a request to open it in that client's workspace, where you price it, log time and move it along.

This list can't be reordered. Priority order belongs to each client's own queue, so drag requests there. Everyone on your agency team can open the list. As everywhere else, prices only show for account owners and admins.

Troubleshooting

The estimate card isn't there. Either you're an account member (pricing is owner/admin only), or the client has already approved the request. An approved job shows its Agreed terms instead and isn't re-priced.

"Nobody will be notified." The workspace has no client to tell — or you are its only client, and nobody is notified of their own send. You can send anyway; the estimate waits in the portal for the first client you invite.

"This work request is not billable yet." It hasn't reached its billable moment. Check the invoice timing on the estimate — if it's set to delivery, mark the request delivered first.

The client says they can't see a request. Check it isn't still a draft. Drafts are invisible to clients by design.

The margin panel says LLM spend is unavailable. The cost ledger couldn't be read. That's a temporary read failure, not a statement that the work was free — retry the page.

Was this helpful?