# Startup Credits Sweep: five rules and a five-check script (free sample)

Version 1.0, 2026-10-29. By PaperChaseWebb. For founders and small teams who want startup credits (cloud, AI API, SaaS) without guessing who qualifies or stretching a fact to fit a form. One Markdown file and one Python 3 script, standard library only. The script was tested on its worked example (5 findings, then 0) and on a missing file (exit 2). It was not run inside any agent harness or on a real application.

Credit directories show headline ceilings ("up to 350,000 USD") copied from other lists, often months old. Forms get filled in a hurry, and four people quietly becomes "a team of six". Credits that do arrive run out after a year, often with a card on file. This sample keeps a small sweep in one JSON file: your facts, each program with its page and the date you read it, the requirements matched against your facts, the answers you plan to give, and the credits you were granted. Five checks catch the common mistakes. The idea of sweeping every program in one pass with an agent comes from a reel by Pratham (@prathamunpluggedd), credited in the full pack.

## Install in one line

Save this page as FREE-SAMPLE.md, then:

```
python3 -c "import re;t=open('FREE-SAMPLE.md').read();open('credits_mini.py','w').write(re.search(r'~~~python\n(.*?)~~~',t,re.S).group(1))"
python3 credits_mini.py credits-lite.json
```

## Five rules

1. **Facts first.** Write down what is true about the company, from records, before you read a single deal: incorporation date, headcount, funding, website, what you build. If you only know it from memory, it is not a fact yet.
2. **The program's own page, with a date.** Not a directory or a thread. Keep the address and the day you read it, keep the "up to" in the benefit, and read the page again if it is more than 30 days old when you apply.
3. **Apply only when every requirement is met by a fact.** A requirement you fail means not eligible. One you cannot answer means check first. Never look for a wording that gets around either.
4. **Answers say your facts word for word.** Four people is "4". No outside funding is not "pre-seed". Never stretch or invent anything to fit a form.
5. **Count credits only after the approval notice, and set a reminder before they expire.** Credits are avoided cost, not revenue and not cash.

Agents read, match and draft. They never submit an application, create an account, accept terms, add a card or spend. The owner does those, by hand.

## The five checks

| Id | Check |
|---|---|
| M1 | every program has its own https page and the date you read it |
| M2 | a program you plan to apply to was read within 30 days of the sweep date |
| M3 | apply only when every requirement is met by one of your facts |
| M4 | every answer contains its cited fact's value word for word |
| M5 | every approved credit has an expiry date and a reminder before it |

## The script

~~~python
#!/usr/bin/env python3
"""credits_mini.py: five checks on a small startup credits sweep (credits-lite.json). Free sample of the Startup Credits Sweep.
Usage: python3 credits_mini.py credits-lite.json
Exit 0 clean, 1 findings, 2 missing or unreadable file. Standard library only. Reads one file, writes nothing."""
import datetime as dt, json, re, sys


def day(s):
    try:
        return dt.date.fromisoformat(str(s))
    except ValueError:
        return None


def check(j):
    F = []
    facts = j.get("facts") or {}
    as_of = day(j.get("as_of")) or dt.date.today()
    for p in j.get("programs") or []:
        pid = p.get("id") or "?"
        acc = day(p.get("accessed"))
        if not str(p.get("source_url", "")).startswith("https://") or not acc:
            F.append(f"M1 program {pid}: give the program's own page and the date you read it")
        elif p.get("verdict") == "apply" and (as_of - acc).days > 30:
            F.append(f"M2 program {pid}: page read {acc}, more than 30 days before {as_of}; read it again before you apply")
        if p.get("verdict") == "apply":
            short = [r.get("need", "?") for r in p.get("requires") or [] if r.get("meets") is not True or r.get("fact") not in facts]
            if short or not p.get("requires"):
                F.append(f"M3 program {pid}: apply only when every requirement is met by one of your facts" + (f" (open: {'; '.join(short)})" if short else ""))
        for a in p.get("answers") or []:
            v = facts.get(a.get("fact"))
            if v is None or not re.search(r"(?<!\w)" + re.escape(str(v)) + r"(?!\w)", str(a.get("a", "")), re.I):
                F.append(f"M4 program {pid}, \"{a.get('q', '?')}\": the answer must say a fact's value word for word, nothing stretched")
    for c in j.get("credits") or []:
        ex, rm = day(c.get("expires_on")), day(c.get("reminder_on"))
        if not ex or not rm or rm >= ex:
            F.append(f"M5 credit {c.get('program', '?')}: an approved credit needs an expiry date and a reminder before it")
    return F


def main(a):
    if len(a) < 2:
        print(__doc__); return 2
    try:
        j = json.load(open(a[1]))
    except (OSError, ValueError) as e:
        print(f"cannot read {a[1]}: {e}", file=sys.stderr); return 2
    if not isinstance(j, dict):
        print(f"cannot read {a[1]}: not a JSON object", file=sys.stderr); return 2
    F = check(j)
    for f in F:
        print(f)
    print(f"5 checks, {len(F)} findings")
    return 1 if F else 0


if __name__ == "__main__":
    sys.exit(main(sys.argv))
~~~

## Worked example

Larkspur Forms is a two-person company making form software for dentists, invented for this sample. Every program here is made up too. Before, saved as credits-lite.json:

```json
{
 "company": "Larkspur Forms, a two-person company making form software for dentists (made up)",
 "as_of": "2026-10-29",
 "facts": {
  "funding": "no outside funding",
  "headcount": "2",
  "website": "https://larkspur.example",
  "founded": "2025-03-02"
 },
 "programs": [
  {
   "id": "nimbus",
   "name": "Nimbus Cloud Starter (made up)",
   "source_url": "https://nimbus.example/startups",
   "accessed": "2026-08-20",
   "verdict": "apply",
   "requires": [
    {
     "need": "Founded in the last 5 years",
     "fact": "founded",
     "meets": true
    }
   ],
   "answers": [
    {
     "q": "Team size",
     "a": "2",
     "fact": "headcount"
    }
   ]
  },
  {
   "id": "ember",
   "name": "Ember AI Credits (made up)",
   "source_url": "",
   "accessed": "",
   "verdict": "check-first",
   "requires": [],
   "answers": []
  },
  {
   "id": "tally",
   "name": "Tally CRM for Startups (made up)",
   "source_url": "https://tally.example/startups",
   "accessed": "2026-10-27",
   "verdict": "apply",
   "requires": [
    {
     "need": "Raised seed or Series A",
     "fact": "funding",
     "meets": false
    }
   ],
   "answers": [
    {
     "q": "Website",
     "a": "https://larkspur.example",
     "fact": "website"
    }
   ]
  },
  {
   "id": "parcel",
   "name": "Parcel Docs for Startups (made up)",
   "source_url": "https://parcel.example/startups",
   "accessed": "2026-10-28",
   "verdict": "apply",
   "requires": [
    {
     "need": "A live website",
     "fact": "website",
     "meets": true
    }
   ],
   "answers": [
    {
     "q": "Team size",
     "a": "We are a team of 5",
     "fact": "headcount"
    }
   ]
  }
 ],
 "credits": [
  {
   "program": "parcel",
   "amount_usd": 600,
   "expires_on": "2027-04-30",
   "reminder_on": ""
  }
 ]
}
```

Run:

```
M2 program nimbus: page read 2026-08-20, more than 30 days before 2026-10-29; read it again before you apply
M1 program ember: give the program's own page and the date you read it
M3 program tally: apply only when every requirement is met by one of your facts (open: Raised seed or Series A)
M4 program parcel, "Team size": the answer must say a fact's value word for word, nothing stretched
M5 credit parcel: an approved credit needs an expiry date and a reminder before it
5 checks, 5 findings
```

The fixes: Nimbus's page is read again on 2026-10-26 and still says the same thing. Ember gets its page and read date (it stays check-first). Tally wants seed or Series A and Larkspur has no outside funding, so Tally becomes not-eligible; nobody rewrites the funding answer. Parcel's answer goes back to "a team of 2", which is what payroll says. And the Parcel credit gets a reminder a month before it expires. After:

```json
{
 "company": "Larkspur Forms, a two-person company making form software for dentists (made up)",
 "as_of": "2026-10-29",
 "facts": {
  "funding": "no outside funding",
  "headcount": "2",
  "website": "https://larkspur.example",
  "founded": "2025-03-02"
 },
 "programs": [
  {
   "id": "nimbus",
   "name": "Nimbus Cloud Starter (made up)",
   "source_url": "https://nimbus.example/startups",
   "accessed": "2026-10-26",
   "verdict": "apply",
   "requires": [
    {
     "need": "Founded in the last 5 years",
     "fact": "founded",
     "meets": true
    }
   ],
   "answers": [
    {
     "q": "Team size",
     "a": "2",
     "fact": "headcount"
    }
   ]
  },
  {
   "id": "ember",
   "name": "Ember AI Credits (made up)",
   "source_url": "https://ember.example/startups",
   "accessed": "2026-10-26",
   "verdict": "check-first",
   "requires": [],
   "answers": []
  },
  {
   "id": "tally",
   "name": "Tally CRM for Startups (made up)",
   "source_url": "https://tally.example/startups",
   "accessed": "2026-10-27",
   "verdict": "not-eligible",
   "requires": [
    {
     "need": "Raised seed or Series A",
     "fact": "funding",
     "meets": false
    }
   ],
   "answers": [
    {
     "q": "Website",
     "a": "https://larkspur.example",
     "fact": "website"
    }
   ]
  },
  {
   "id": "parcel",
   "name": "Parcel Docs for Startups (made up)",
   "source_url": "https://parcel.example/startups",
   "accessed": "2026-10-28",
   "verdict": "apply",
   "requires": [
    {
     "need": "A live website",
     "fact": "website",
     "meets": true
    }
   ],
   "answers": [
    {
     "q": "Team size",
     "a": "We are a team of 2",
     "fact": "headcount"
    }
   ]
  }
 ],
 "credits": [
  {
   "program": "parcel",
   "amount_usd": 600,
   "expires_on": "2027-04-30",
   "reminder_on": "2027-03-31"
  }
 ]
}
```

```
5 checks, 0 findings
```

Tally is still not for Larkspur, and that is the right answer.

## One prompt to try

Paste into your agent: "Here are my company facts, each with the record it comes from: [facts]. Read the startup program pages for [programs] yourself, not a directory. For each one, give me the page, today's date, the benefit as written with any 'up to' kept, and each requirement marked meets, fails or unknown against one of my facts. Apply only where everything meets. Draft answers that use my facts word for word, and mark anything you do not have as NEEDS OWNER INPUT. Do not submit anything, create accounts or accept terms."

## The full pack

The paid Startup Credits Sweep (pp-startup-credits-sweep, $19) grows this into a sweep you can keep running: facts with their records and a settled status, a matrix that sets each verdict, application drafts that cite every fact, a ledger that counts nothing before approval and reminds you before every expiry, fifteen checks, a one-page sweep report, starter rows for seven real programs read on 2026-10-29, and every application waiting for the owner's yes, tied to its sha256 and typed at their own terminal, before the owner submits it by hand. If you would rather have it set up with you, book a call from the home page at paperchasewebb.ai.

Made-up example; the company, people, programs and facts are invented.

PaperChaseWebb 💸
