corporate-registry
v0.2.0
Published
New York and New Jersey company registry search — entity lookup, filing history, prior names, mergers and DBAs, from the public state registries
Maintainers
Readme
corporate-registry
New York and New Jersey company registry search, as one CLI and library.
npx --yes corporate-registry search "ACME" --limit 5Both registries are public records — no account, no login, no captcha, no API key. Every operation is one HTTP call and prints JSON on stdout.
Built on website-api.
The two registries
| | New York (--state ny, default) | New Jersey (--state nj) |
| --- | --- | --- |
| Source | NYS Department of State | NJ Division of Revenue |
| Interface | public JSON API | HTML form, scraped |
| Auth | none | per-search anti-forgery token |
| Operations | 7 — search plus five lookups | 1 search; no per-entity detail |
| Filters | status, entity type, expression | name only |
| Ceiling | 300 rows | 500 rows |
New Jersey genuinely has no per-company detail — the registry exposes one search and nothing else.
Operations
| Operation | Registry | Answers |
| --- | --- | --- |
| search | both | Companies by name; New York also by DOS ID |
| details | ny | Every by-ID lookup for one company, in one call |
| entity-record | ny | Address, registered agent, jurisdiction, status |
| name-history | ny | Prior legal names |
| filing-history | ny | Every filing, with type and date |
| merger-history | ny | Mergers and consolidations |
| assumed-name-history | ny | DBAs, with filing and expiry dates |
| entity-types | nj | What each New Jersey type code means |
An operation on only one registry routes itself; only search needs --state.
npx --yes corporate-registry --listreturns the machine-readable inventory — every operation with its options, types and defaults, read off the site definitions so it cannot drift.
Output
JSON by default. --format tsv or --format csv with --fields returns a flat
table instead, so nothing downstream has to parse JSON or fight shell quoting:
npx --yes corporate-registry ny search "mazu" --format tsv --fields id,name,status,countyA field no row carries is an error listing the real ones, rather than a silent
column of blanks. details has no table form — it returns five keyed lookups
rather than one list.
Examples
npx --yes corporate-registry search 4809335
npx --yes corporate-registry search "GOOGLE" --status Active --entity-type LimitedLiabilityCompany
npx --yes corporate-registry details --dos-id 4809335 --entity-name "GOOGLE ACCESS LLC"
npx --yes corporate-registry search "ACME" --state nj --limit 5
npx --yes corporate-registry entity-typesLibrary use
import { runSite } from "website-api";
import { nySite, njSite } from "corporate-registry";
const result = await runSite(nySite, { operation: "search", term: "ACME", limit: 5 });Both sites declare transport: "http", so they also run on Cloudflare Workers
through website-api/worker.
For agents
skill.md is the agent-facing guide: how to run each operation, how
to read the output, and which failures are worth branching on. Every command in
it is executed by test:skill, so it cannot drift from the tool.
Registry quirks worth knowing
Neither registry can page. --start/--limit are applied to the results
after they arrive. New York's history endpoints additionally return the same rows
in a different order on each call — three distinct orderings in five calls,
verified live — so history lists are sorted newest-first here before windowing,
which is the only thing that makes --start reproducible. New York's search ignores listEndRecord and returns zero
rows for a listStartRecord above 1; its history endpoints ignore
listEndRecord too; New Jersey's form takes no page parameter at all. So a large
--start costs the same as a small one. matched reports the total before
windowing, and truncated reports hitting the ceiling.
New York spells its request fields two ways — camelCase for the search,
PascalCase for every by-ID lookup — and GetEntityRecordByID takes only the
SearchID; sending it the name and pagination the histories require makes it
answer with the wrong record. Failures arrive as HTTP 200 with
requestStatus: "Failure".
New Jersey is ASP.NET MVC with [ValidateAntiForgeryToken]: the hidden field
and the cookie must be a matched pair from one GET, and they expire, so each
search fetches its own. A term under 2 characters is refused by the registry with
"Invalid Search" — reported as an error, not as zero results. Its Type cell
renders as <abbr title="Domestic Profit Corporation">DP</abbr>, so both forms
are returned, as type and typeCode.
Testing
npm run test:live # all 9 operations against the real registries
npm run test:skill # every command in skill.md, run for realLicense
MIT
