New York Liquor License Renewal & Expiry Watch avatar

New York Liquor License Renewal & Expiry Watch

Pricing

from $0.025 / actor start

Go to Apify Store
New York Liquor License Renewal & Expiry Watch

New York Liquor License Renewal & Expiry Watch

Check NY SLA serial numbers and permit IDs for published expiration and renewal-date changes. Preserve multiple permits, compare portfolios and flag upcoming dates in JSON.

Pricing

from $0.025 / actor start

Rating

0.0

(0)

Developer

Michal Pšenčík

Michal Pšenčík

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Check a portfolio of New York State Liquor Authority (SLA) legacy serial numbers and current permit IDs against the official Current Liquor Authority Active Licenses dataset on data.ny.gov (Socrata dataset 9s3h-dpkz, posted daily). For each identifier you supply, the Actor returns one complete check with every matching permit, the published issue, effective and expiration dates, days to the published expiry and reminder flags. With a watch ID it compares each check with the last one it delivered and tells you what changed.

Built for distributors, license consultants and hospitality operators who already know their NY identifiers and recheck them weekly, or daily near expiry, from a schedule or an integration.

What it does not do: it does not discover licenses, file renewals, send email or SMS, derive legal filing deadlines, follow parent/child links, or cover inactive licenses. An identifier missing from the active feed does not prove a closure, revocation or that a license is invalid: it only means the current active list does not contain it.

Input

{
"identifiers": [
{ "kind": "legacy_serial", "value": "6085646" },
{ "kind": "legacy_serial", "value": "3171641" },
{ "kind": "permit_id", "value": "0370-24-131229-01" },
{ "kind": "legacy_serial", "value": "0000000" }
],
"watchId": null,
"reminderDays": [90, 30, 7],
"maxItems": 2000,
"requestIntervalMs": 1300
}
  • identifiers (1 to 2,000): legacy_serial values are 1 to 20 digits and keep leading zeroes; permit_id values look like 0001-26-135216 or 0343-23-306684-01. Matching is exact, never numeric or fuzzy. Exact repeats are checked once. A serial and a permit ID for the same license are two checks and both may bill.
  • watchId (optional, letters, digits, _ and -, up to 64): turns on comparison with the last delivered check for each identifier. Leave it empty for a stateless snapshot. Run one schedule per watch ID at a time; overlapping runs on one watch are refused when detected, but simultaneous starts can race. A new watch ID is a reset.
  • reminderDays (1 to 3 values, 0 to 365): a permit is flagged when its published expiry is within that many calendar days.
  • maxItems (1 to 2,000): stop after this many delivered checks.
  • requestIntervalMs (1,300 to 10,000): idle time after each source response before the next request.

The default input checks one real serial (6085646) so the Actor always returns a row. A field left out takes its default; a field set to null is rejected before any request, except watchId, where null means no watch.

Output

One LICENSE_CHECK item per matched identifier, in input order, including unchanged ones. A shortened real example (serial 6085646, snapshot mode):

{
"recordType": "LICENSE_CHECK",
"recordId": "ny-sla:legacy_serial:6085646",
"watchId": null,
"request": { "kind": "legacy_serial", "value": "6085646" },
"matchStatus": "matched",
"changeKind": "snapshot",
"previousHash": null,
"contentHash": "092715d9bbe403802be582f9d92f23c1274f30088d57f782801cb5ccfd65febf",
"permitCount": 1,
"sourceRowCount": 1,
"matches": [
{
"licensePermitId": "0001-26-135216",
"variants": [
{
"legacySerialNumber": "6085646",
"parentLicenseId": null,
"legalName": "Guru Hari 394 Inc.",
"dba": null,
"classCode": "0001",
"description": "Wholesale Beer (Retail)",
"premisesCounty": "Suffolk",
"rawDates": {
"lastIssueDate": "2026-02-10T00:00:00.000",
"expirationDate": "2027-01-31T00:00:00.000"
},
"dates": { "lastIssueDate": "2026-02-10", "expirationDate": "2027-01-31" },
"sourceRowIds": ["row-3ij9-tbne~ek3x"],
"daysToPublishedExpiry": 107
}
]
}
],
"changes": [],
"reminders": [],
"warnings": [],
"observedAt": "2026-10-16T14:43:38.975Z",
"calendarTimezone": "America/New_York",
"sourceTimezone": null,
"coverage": {
"completeForRequestedIdentifier": true,
"datasetId": "9s3h-dpkz",
"sourceUrls": ["https://data.ny.gov/resource/9s3h-dpkz.json?..."]
}
}

(dates and rawDates always carry all four fields: originalIssueDate, lastIssueDate, effectiveDate, expirationDate; the example drops two for space.)

  • Multiple permits and variants. A serial can return several current permits (3171641 returns a hotel permit and its additional bar). The source's "unique" permit ID is not always unique: when two rows for one permit differ (for example a null versus a populated parent link), both are kept as variants with a multiple_source_variants:<permit> warning. Nothing is merged, picked or filled in.
  • Dates. The source publishes floating timestamps with no time zone. Raw strings are kept as published and the calendar date is used as is. Day counts use the New York calendar on the day the run started (an Actor choice, not a publisher declaration). Past dates give negative counts.
  • Watch mode. changeKind is baseline on the first delivered check, then unchanged or changed (any correction, including backwards date changes, parent or name corrections). changes[] lists each permit that appeared, is not in the current result, or whose variants changed, with before and after date tuples. A permit that disappears is "not in current result", never "deleted" or "revoked".
  • Reminders. For each permit with one published expiry, one entry per threshold it is within, with newlyDue true the first time a watch reports that permit, expiry and threshold (null in snapshot mode). Variants with conflicting expiries suppress that permit's reminders with an expiry_conflict warning. These are JSON flags for your own automation, not notifications.

The free SUMMARY record in the run's key-value store lists every input with its outcome (delivered, duplicate, not_in_current_active_feed, error, not_attempted_cap, delivery_uncertain), error details, source versions, request counts and the identifiers a later run can retry. If the platform restarts a run, its counts and source versions carry over and an identifier fetched again is counted once (attemptedIdentifiers and the input indexes in attemptedIndexes). No-match results and errors appear only there.

Pricing

Pay per event:

  • Actor start: $0.025 per run start, charged even when the run finds nothing or fails. The higher start fee covers slow, empty and error runs that deliver no billable item.
  • License check: $0.001 per delivered matched identifier check, including unchanged checks (each is the checked current record and its receipt). One check can hold several permits and variants.

Identifiers not in the active feed, invalid input, incomplete or failed source batches, failed deliveries and the SUMMARY record are not charged as items. A run with 500 matched identifiers costs $0.025 + 500 × $0.001 = $0.525 in event fees.

With a maximum total charge set on the run, the Actor keeps room for the start fee and stores only the checks the rest of the limit covers. Identifiers it could not afford are listed in SUMMARY as not_attempted_cap with code spending_limit, the run ends as capped, and a later run can retry them.

Limits and behaviour

  • One request at a time to data.ny.gov, at least 1.3 s idle after each response, 20 s per attempt, at most 120 attempts, 2 MiB per response, 16 MiB per run and a 600-second work deadline. Identifiers are queried 25 at a time with $limit=100 pages; a batch that needs more than 10 pages or returns more than 50 rows for one identifier is reported as an error instead of being truncated.
  • Timeouts and server errors are retried twice. HTTP 401, 402, 403, 429 or a bot challenge stops all requests for the run; a Retry-After is reported as retryNotBefore. There is no proxy, login, token or browser fallback.
  • If the source version headers differ between pages of one batch, that batch fails and is listed for retry. Equal headers are a consistency check, not a guaranteed snapshot.
  • Watch state is limited to 2,000 identifiers, 128 KiB per identifier and 32 MiB per watch, with at most four expiry dates and twelve reminder keys per permit; a check that would pass these limits is an error, nothing is evicted.
  • Delivery and state are not one transaction: after a crash a later run can repeat a change or reminder (at-least-once).

Source and data notes

Data comes from the New York State Liquor Authority's current active licenses dataset, published on data.ny.gov through the Socrata open data API without a key. Legal names are returned exactly as published; you are the controller of any processing of that data. The SLA itself sends renewal advisories about three months before expiry; this Actor is a data check, not legal advice or confirmation that a license is valid.

Support

Open an issue on the Actor's Issues tab with the run ID and the SUMMARY record.