# New Orleans Permits - Building & Trade Register (`j0401/nola-permits`) Actor

City of New Orleans building and trade permits (public open data, 348,207 permits, 2006-today): type, status and its date, owner, applicant and contractor, construction value and fees, parcel PIN, address and zoning. Filter by type, status, contractor, value or date.

- **URL**: https://apify.com/j0401/nola-permits.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 new orleans permit records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## New Orleans Permits - Building & Trade Permit Register

Every permit the City of New Orleans Department of Safety & Permits has
processed, straight from the City's own open data portal. **~348k permits,
predominantly 2006 onward.**

### Low cost

**From $0.00005 per record, down to $0.00003 at Gold.** Pay only for the
records you actually receive - the whole register stays queryable, you are
never billed for the scan behind it.

### What you get

This is a **full permit lifecycle**, not a snapshot - each row carries its
filing date, its issue date, its current status and the date that status was
set, plus the counters the City precomputes:

- **The permit** - number, type (electrical, mechanical, renovation, solar,
  lead-based paint, ), the internal code and the project description
- **The lifecycle** - filing date, issue date, current status and its date,
  next status and its date, `daysOpen`, `daysIssued`, inspection count and open
  comments
- **The parties** - owner, applicant and contractor, where the City recorded
  them
- **The money** - the declared construction value, total fees and bond amount
- **The place** - site address, parcel PIN, zoning, land use, historic district,
  subdivision and council district

### Modes

- **rows** (default) - permit records matching your filters
- **aggregate** - counts by permit type, land use, council district, lead
  agency, exit reason or zoning

### Filters

Permit number, type, current status, open/closed, description, owner,
applicant, contractor, address, ZIP, parcel PIN, council district, land use,
lead agency, zoning, a minimum construction value, and true issue-date and
filing-date ranges.

### Example inputs

**Large renovations issued this month**

```json
{ "type": "Renovation", "minConstructionValue": 250000, "maxResults": 25 }
```

**Permits issued but not yet closed** - the open book. Note that `Permit
Expired` is *closed* by definition; `Permit Issued` is the status that stays
open.

```json
{ "isClosed": "false", "status": "Permit Issued", "maxResults": 25 }
```

**One contractor's permits** - note that a contractor is recorded on about
72% of rows.

```json
{ "contractor": "LLC", "minConstructionValue": 100000, "maxResults": 25 }
```

**A council district, one month**

```json
{
  "councilDistrict": "B",
  "issuedFrom": "2026-09-01",
  "issuedTo": "2026-09-30"
}
```

### Example output

**A renovation above $250k** - `type=Renovation`,
`minConstructionValue=250000`:

```json
{
 "platform": "nola-permits",
 "source": "nola-one-stop-permits",
 "corpus": "permits",
 "recordKind": "permit",
 "mode": "rows",
 "groupKey": "",
 "groupCount": "",
 "groupBy": "",
 "permitNumber": "26-17120-RNVN",
 "type": "Renovation (Non-Structural)",
 "code": "RNVN",
 "description": "Non-structural renovation of existing outdoor space including drainage improvements, new groundcover, paving, planting, play equipment, and artificial turf. There is no change in occupancy or use.",
 "currentStatus": "Permit Issued",
 "nextStatus": "Inspections Finaled",
 "isClosed": "false",
 "address": "1651 N Tonti St",
 "owner": "Orleans Parish School Board Mc Donough 42 Elementary",
 "applicant": "Angela Morton",
 "contractors": "Land Craft Design Build LLC",
 "leadAgency": "City of New Orleans",
 "filingDate": "2026-06-08",
 "issueDate": "2026-09-25",
 "currentStatusDate": "2026-09-25",
 "nextStatusDate": "2026-12-24",
 "daysOpen": "109",
 "daysIssued": "0",
 "totalInspections": "3",
 "openComments": "0",
 "exitReason": "",
 "constructionValue": "455500",
 "totalFees": "2796",
 "bondAmount": "0",
 "pin": "37W205923",
 "councilDistrict": "D",
 "zoning": "HU-RD2",
 "landUse": "Business Use",
 "landUseShort": "COMM",
 "historicDistrict": "",
 "subdivision": "Seventh Ward",
 "sourceUpdatedAt": "2026-09-26"
}
```

**`mode=aggregate`, `groupBy=type`** - one count row per permit type:

```
Electrical Service / Circuit / Feeder           56,315
Renovation (Non-Structural)                     46,638
Mechanical Fuel Gas                             39,913
Mechanical HVAC                                 31,469
Electrical Repair / Replacement / Addition      30,609
General Mechanical                              25,195
```

### Notes on the data, from the source

- **The applicant is near-universal; owner and contractor are majority but not
  complete.** The applicant is recorded on 99% of rows, the **owner on 74%**
  and the **contractor on 72%** (92,097 and 96,636 blanks out of ~348k). A
  permit that names every party cannot be promised, so this actor does not.
- **Six source columns carry no usable data and are not published**: `division`
  (the single constant `SP` on all ~348k rows), building area (zero or null
  on 96.6%), beds (zero on 94%), baths (zero on 93%), unpaid fees (non-zero on
  2%) and the project name (populated on ~1,095 rows, 0.3%). Building area in
  particular reads like the square footage a permit dataset should have - on
  this source the usable size proxy is the declared construction value, which
  is non-zero on 56.6% of rows.
- **The open/closed flag is text with case variants** - `True` (305,762) and
  `true` (29) mean closed, `False` (41,285) and `false` (1,131) mean open. It is
  normalised to a real `true` / `false` on output, and the filter is
  case-insensitive so none of the 1,160 lowercase rows are unreachable.
- **Most permits are closed.** Only about 12% (42,416 of ~348k) are open, and
  the open book is dominated by `Permit Issued`. A status like `Permit Expired`
  is *always* closed, so pairing it with `isClosed=false` correctly returns
  nothing.
- **Council districts are letters (A-E), not numbers**, and the source carries
  dirty variants with a trailing comma (`B,` alongside `B`) plus 21,795 blanks.
  The comma is stripped on output.
- **There is no ZIP column.** ZIP filtering matches digits appearing in the
  site address.
- **The register is overwhelmingly 2006 onward.** One row predates it (the
  earliest filing date is 2002-02-03) and the permit numbering scheme starts in
  2006; read the range as "the modern One Stop system", not as a hard floor.
- **Status fields are excluded from aggregation.** `currentStatus` has 114
  values and `nextStatus` is populated on only 13% of rows - the first is a
  lifecycle state better filtered than counted, the second is mostly blank.
- **Issue and filing dates are true dates**, so these are real ranges, not the
  year-granularity that text date columns force.

### Notes

- Public open data from data.nola.gov. No login, no scraping.
- Permits are issued daily; every record carries `sourceUpdatedAt` so you can
  see the feed's currency without running anything.
- Charges are metered per record delivered, so a targeted query costs a
  fraction of a cent.

# Actor input Schema

## `mode` (type: `string`):

rows = records matching your filters (default). aggregate = one count row per group.

## `groupBy` (type: `string`):

Aggregate dimension, only used when mode=aggregate.

## `permitNumber` (type: `string`):

Exact permit number, e.g. '26-27777-FGAS'. Blank = any.

## `type` (type: `string`):

Permit-type substring, e.g. 'Electrical', 'Renovation', 'Mechanical'. Blank = any. 68 types in total.

## `status` (type: `string`):

Current-status substring, e.g. 'Permit Issued', 'Finaled', 'Permit Expired'. Blank = any.

## `isClosed` (type: `string`):

true = closed, false = open. Blank = both.

## `description` (type: `string`):

Project-description substring. Blank = any.

## `owner` (type: `string`):

Owner-name substring. Blank = any. NOTE: owner is recorded on about 74% of rows.

## `applicant` (type: `string`):

Applicant-name substring. Blank = any. Present on 99% of rows.

## `contractor` (type: `string`):

Contractor-name substring. Blank = any. NOTE: recorded on about 72% of rows.

## `address` (type: `string`):

Site-address substring, e.g. 'Banks St'. Blank = any.

## `zip` (type: `string`):

ZIP digits appearing in the site address. Blank = any.

## `pin` (type: `string`):

Exact parcel PIN. Blank = any.

## `councilDistrict` (type: `string`):

Council district code, e.g. 'B'. Blank = any.

## `landUse` (type: `string`):

Land-use substring. Blank = any.

## `leadAgency` (type: `string`):

Lead-agency substring. Blank = any.

## `zoning` (type: `string`):

Zoning substring, e.g. 'HU-RD2', 'S-RS'. Blank = any.

## `minConstructionValue` (type: `integer`):

Only permits with a declared construction value at least this, e.g. 100000. Blank = any. ~43% of rows declare no value and will not match.

## `issuedFrom` (type: `string`):

YYYY-MM-DD. True date range. Blank = any.

## `issuedTo` (type: `string`):

YYYY-MM-DD. Blank = any.

## `filedFrom` (type: `string`):

YYYY-MM-DD. Blank = any.

## `filedTo` (type: `string`):

YYYY-MM-DD. Blank = any.

## `maxResults` (type: `integer`):

Cap records returned for this run. Default 50 keeps the daily auto-test fast. 0 = no cap (the full matching slice, up to 10,000).

## Actor input object example

```json
{
  "mode": "rows",
  "groupBy": "type",
  "permitNumber": "",
  "type": "",
  "status": "",
  "isClosed": "",
  "description": "",
  "owner": "",
  "applicant": "",
  "contractor": "",
  "address": "",
  "zip": "",
  "pin": "",
  "councilDistrict": "",
  "landUse": "",
  "leadAgency": "",
  "zoning": "",
  "issuedFrom": "",
  "issuedTo": "",
  "filedFrom": "",
  "filedTo": "",
  "maxResults": 50
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

New Orleans Permits - Building & Trade Permit Register - as JSON

## `datasetUrl` (type: `string`):

No description

## `runUrl` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/nola-permits").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("j0401/nola-permits").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call j0401/nola-permits --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/nola-permits"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/9mqaGnZ5D5hoOjp7R/builds/EC5uKBiqMge9hS3Pj/openapi.json
