Estimated payment

The running jobjob_4Tx2 · delivered · workpapers-2026.txt · return.txt · $1,800.00 charged

A quarter's estimated tax in each jurisdiction, figured, decided and paid. The prior-year safe harbor, cumulative by quarter so a quarter figured short catches up, California's 30, 40, 0 and 30, New York's first installment on its extension, and what an unpaid installment costs.

tax's wordsreturn is a jobtaxpayer is a subjectreview is a taskpreparer is a member

A C corp pays its tax in four installments, and each state keeps its own. The Estimated Payment figures each one, the officer decides, and the brand pays it. The quarter is its period, and what was paid is kept by quarter for the year's return to credit.

Run
cat services/estimate.ts
magic values: none
import { Service } from 'services.dev'
import { estimateDue, estimateFor, underpaymentCost } from '../lib/tax.ts'

// A quarter's estimated payments, the owner deciding. The quarter is its period on the taxpayer, so a second estimate for
// the same quarter answers period_taken. Your code figures each jurisdiction's installment: what the year requires by
// this quarter on last year's tax, less what is paid, so a quarter figured short catches up. The owner pays it, pays a
// different amount themselves, or skips it in writing. Paid, each payment goes under a cap, its receipt satisfies the
// clock the buyer answers for, and what was paid is kept on the taxpayer, in its quarter, for the year's return to credit.
// The estimate is earned once it is figured and decided, so it is charged on delivery, whatever the owner chose.
const decided = (job: { record: readonly { step?: string; decided?: string }[] }) => job.record.findLast(e => e.step === 'approve' && e.decided)?.decided

export default Service({
  name: 'Estimated Payment',
  description: "A quarter's estimated tax, figured, decided and paid.",
  input: { owner: 'party: the officer who decides', ein: 'text: such as 12-3456789', quarter: 'text: such as 2027-Q1', jurisdictions: 'jurisdiction[]: such as US, US-CA' },
  output: { amount: 'money{}', basis: 'text', voucher: 'file', receipt: 'text[]?', paid: 'money{}?' },
  subject: { kind: 'taxpayer', key: 'ein', period: 'quarter', keeps: { paid: 'paid' } },
  deliver: {
    compute: { by: estimateFor, cite: 'prior-year safe harbor, cumulative by quarter' },
    approve: { ask: 'owner', to: 'decide', choices: ['pay it', 'pay a different amount', 'skip, in writing'] },
Run
npx services.dev check
magic values: none
services/estimate.ts · 17 lines · $79 per job, within 48 hours, charged on delivery.
  steps   compute · code · cites prior-year safe harbor, cumulative by quarter → approve · owner · decide → review · ai · adversarial → pay · Treasury and states · one for each jurisdiction with an installment → record · code
  clocks  pay · a date your code decides · the buyer · about 7% a year on an installment left unpaid

estimateFor in lib/tax.ts figures what the year requires by this quarter, less what is already paid, in each jurisdiction:

JurisdictionShare due by each quarterThe first installment
US25%, 50%, 75%, 100%with the first estimate
California30%, 70%, 70%, 100%: nothing in the thirdwith the first estimate
New York25%, 50%, 75%, 100%with last year's CT-5 extension, a quarter of that year's tax
New Jersey25%, 50%, 75%, 100%with the first estimate

The basis is last year's tax, the safe harbor; before that return is filed, the latest year on file. A large corporation, $1 million of taxable income in any of the three years before, may use last year's tax for its first installment only.

Acme's first two quarters were figured on 2025. By September 2026's return was in, and the third quarter catches up the $4,410 the first two were short:

Run
npx services.dev tick 1y --test-clock tc_7Hq4 --market normal
magic values: owner.email = signs@example.test, metadata.sandbox.asks = {"organizer.books":"after 160d","organizer.assets":"waive","organizer #2":"after 2d","w9":"after 19d"}, metadata.sandbox.outside = {"reject":{"file.US-NY":["ein_mismatch"]}}, metadata.sandbox.events = { notice.received: { at: 2027-11-14T15:00:00Z, data: { notice, reply_by, tax_years } } }
  2027-04-05 13:00:00  job_4Tx4  compute · 2026 isn't filed yet: 2025's tax (job_4Tx2) · US $16,223 · US-CA $1,639 · US-NJ $1,391 · US-NY's first installment goes with its CT-5
  2027-06-05 13:00:00  job_4Tx5  compute · 2026 isn't filed yet: 2025's tax (job_4Tx2) · US $16,222 · US-CA $2,185 · US-NY $1,447 · US-NJ $1,390
  2027-09-05 13:00:00  job_4Tx6  compute · 2026's tax (job_4Tx3), the safe harbor · US $22,838, catching up the $4,410 Q1 and Q2 were short of it · US-NY $2,356 · US-NJ $1,958 · US-CA has no third installment
  2027-12-05 14:00:00  job_4Tx8  compute · 2026's tax (job_4Tx3), the safe harbor · US $18,427 · US-CA $2,381 · US-NY $1,901 · US-NJ $1,579

Each clock carries what an unpaid installment costs at the Form 2220 rate, 7% a year here.

She pays it, pays a different amount herself, or skips it in writing. It's charged on delivery, whatever she chose:

captured/tax-branches.txt · magic values: owner.email = signs@example.test, owner.email = declines@example.test, owner.email = silent@example.test, metadata.sandbox.asks = { approve: pay it }, metadata.sandbox.asks = { approve: pay a different amount }, metadata.sandbox.asks = { approve: skip, in writing }, metadata.sandbox.outside = never, metadata.sandbox.brand = stale, metadata.sandbox.brand = verified, member = mbr_eligible, member = mbr_lapsed_credential
→ POST /returns {"service":"estimate","owner":{"name":"Ada","email":"signs@example.test"},"ein":"12-3456789","quarter":"2027-Q1","jurisdictions":["US","US-CA"],"max_usd":79,"key":"pay it","metadata":{"sandbox":{"asks":{"approve":"pay it"}}}}   # metadata.sandbox.asks = { approve: pay it }
← job_4Tx2 · delivered · voucher.txt · $79.00 charged
captured/tax-branches.txt · magic values: owner.email = signs@example.test, owner.email = declines@example.test, owner.email = silent@example.test, metadata.sandbox.asks = { approve: pay it }, metadata.sandbox.asks = { approve: pay a different amount }, metadata.sandbox.asks = { approve: skip, in writing }, metadata.sandbox.outside = never, metadata.sandbox.brand = stale, metadata.sandbox.brand = verified, member = mbr_eligible, member = mbr_lapsed_credential
→ POST /returns {"service":"estimate","owner":{"name":"Ada","email":"signs@example.test"},"ein":"12-3456789","quarter":"2027-Q1","jurisdictions":["US","US-CA"],"max_usd":79,"key":"skip, in writing","metadata":{"sandbox":{"asks":{"approve":"skip, in writing"}}}}   # metadata.sandbox.asks = { approve: skip, in writing }
← job_4Tx2 · delivered · voucher.txt · $79.00 charged

A year, and the next runs all four quarters, and the Tax Plan orders each ten days before it's due.