---
title: "Information returns"
url: https://services.dev/docs/examples/tax/information-returns
captured: [tax-build.txt, tax-check.txt, tax-years.txt]
---
# Information returns

URL: https://services.dev/docs/examples/tax/information-returns

> The calendar year's 1099s, filed by 31 January. AI reads the ledger for each vendor paid $600 or more, a W-9 is asked of each payee without one, every name and TIN is matched under the brand's own TIN matching, and the 1099-NECs are e-filed under its transmitter code, $15 a payee.

*tax's words: return is a job, taxpayer is a subject, review is a task, preparer is a member (examples/tax/brand.ts).*

Every business that pays a contractor owes the year's 1099s by 31 January, whatever its tax year. Information Returns files them: the AI reads the ledger, your code lists each vendor paid $600 or more for services, each payee without a W-9 on file is asked for one, every name and TIN is matched, the officer confirms the list, and the 1099-NECs go to the IRS and to each payee.

```bash
cat services/information-returns.ts
```

```txt title="magic values: none"
import { Service } from 'services.dev'
import { payees } from '../lib/tax.ts'
import rules from '../rules.ts'

// The calendar year's 1099s, by 31 January, whatever the tax year. The AI reads the ledger for every vendor paid $600 or
// more for services, your code lists them, and each payee with no W-9 on file is asked for one. Every name and TIN is
// matched under the brand's own TIN matching, the officer confirms the list, and the 1099-NECs are e-filed under the
// brand's transmitter code and sent to each payee. $15 a payee; the Tax Plan includes 25 a year. The date is the brand's.
export default Service({
  name: 'Information Returns',
  description: "The year's 1099s, filed by 31 January.",
  input: { owner: 'party: the officer who confirms', ein: 'text: such as 12-3456789', year: 'text: the calendar year, such as 2026', books: 'url: a read-only link to the ledger, such as https://books.example/acme' },
  output: { ledger: 'json: each payment to a vendor', payees: 'number', w9_asked: 'text[]', forms: 'file', receipt: 'text' },
  rules,
  subject: { kind: 'taxpayer', key: 'ein', period: 'year' },
  deliver: {
    read: { by: 'ai', cite: "the ledger's payments to each vendor" },
    list: { by: payees, cite: 'every payee paid $600 or more for services' },
    w9: { ask: 'each payee', to: 'upload', what: 'Form W-9', for: 'w9_asked', expires: '21d' },
    match: { submit: 'https://tin-matching.example.test/match', to: 'TIN matching', receipt: 'receipt' },
    confirm: { ask: 'owner', to: 'decide', choices: ['file them', 'hold one, in writing'] },
    file: { submit: 'https://iris.example.test/submit', to: 'IRS, through IRIS', receipt: 'receipt' },
    send: { by: 'ai', cite: "each payee's copy, by mail, or by email where they consented" },
  },
  clocks: { file: { due: job => `${Number(job.input.year) + 1}-01-31`, owner: 'brand', rungs: ['notice 14d', 'escalate 3d'] } },
  price: { usd: 15, per: 'payees', release: 'file' },
})
```

```bash
npx services.dev check
```

```txt title="magic values: none"
services/information-returns.ts · 17 lines · $15 per payee, charged when file is accepted.
  subject taxpayer · keyed by ein · one a calendar year
  bounds  open match, under the brand's tin_matching · open file, under the brand's iris
  ledger  +$90.00 · AI $0.84 (example) · you $89.16 · 6 payees
```

## Under the brand's own codes

A 1099 reports a payment; it isn't a return, so no PTIN signs it. The brand matches each TIN under its own TIN matching and files under its own transmitter code, two rows of [the rules table](https://services.dev/docs/examples/tax/rules.md) and two credentials in `brand.ts`. The date is the brand's to answer for.

## On the plan

The Tax Plan orders it five days after each calendar year ends, 25 payees a year inside the allowance. A plan bought in January catches up the year just ended: Acme's 2026 1099s were due 31 January 2027, a Sunday, so 1 February:

```bash
npx services.dev tick 1y --test-clock tc_7Hq4 --market normal
```

```txt title="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-01-20 09:00:00  job_4Tx1  read → list · 5 payees, each W-9 on file
  2027-01-20 09:00:00  job_4Tx1  match · TIN matching · 5 matched
  2027-01-20 09:00:00  job_4Tx1  ask confirm · signs@example.test · decided "file them"
  2027-01-20 09:00:00  job_4Tx1  file · IRS, through IRIS · 5 1099-NECs accepted · due 2027-02-01
  2027-01-20 09:00:00  job_4Tx1  send · 5 payee copies · delivered · collected $0.00 · allowance 5 of 25
  2027-01-27 09:00:00  job_4Tx1  accepted · earned $0.00
```

## A W-9 that comes late

In January 2028 one vendor had no W-9 on file. The ask waited 19 days, TIN matching cleared all six, and the filing went in on 27 January, four days before its date:

```bash
npx services.dev tick 1y --test-clock tc_7Hq4 --market normal
```

```txt title="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 } } }"
  2028-01-05 14:00:00  job_4TxA  read → list · 6 payees · 1 W-9 not on file: Lumen Design LLC
  2028-01-05 14:00:00  job_4TxA  ask w9 · Lumen Design LLC · Form W-9 · open
  2028-01-05 14:00:00  job_4TxA  waits on party at w9
  2028-01-17 14:00:00  job_4TxA  clock file · rung notice 14d · due 2028-01-31 · owner brand
```

```bash
npx services.dev tick 13d --test-clock tc_7Hq4 --market normal
```

```txt title="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 } } }"
  2028-01-24 14:00:00  job_4TxA  ask w9 · Lumen Design LLC · uploaded
  2028-01-24 14:00:00  job_4TxA  match · TIN matching · 6 matched
  2028-01-24 14:00:00  job_4TxA  ask confirm · signs@example.test · decided "file them"
  2028-01-27 14:00:00  job_4TxA  file · IRS, through IRIS · 6 1099-NECs accepted · due 2028-01-31
  2028-01-27 14:00:00  job_4TxA  send · 6 payee copies · delivered · collected $0.00 · allowance 11 of 25, cycle 1
```

[The Tax Plan](https://services.dev/docs/examples/tax/tax-plan.md) covers its allowance, and [Take your first real return](https://services.dev/docs/examples/tax/launch.md) the systems behind TIN matching and the filing.

---

- Up: [The tax example](https://services.dev/docs/examples/tax.md)
- Previous: [Year-end close](https://services.dev/docs/examples/tax/year-end-close.md)
- Next: [Tax transcript](https://services.dev/docs/examples/tax/transcript.md)
