> ## Documentation Index
> Fetch the complete documentation index at: https://ploti.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom feeds

> Describe the table your system needs. Ploti checks what it holds, proposes the feeds with a prediction for every column, collects what is missing, and keeps the result current.

A custom feed is a table Ploti builds to the schema you describe and delivers into your own systems. It is made from the official county and city records Ploti collects, such as parcels, permits, zoning and flood zones, combined for you and kept current as each source changes.

Use one when your system needs data in a set shape before it can load it. When you can load each dataset as its source publishes it and combine them yourself, a [source feed](https://ploti.ai/docs/feeds/source-and-custom-feeds.md) gives you more. [Source feeds and custom feeds](https://ploti.ai/docs/feeds/source-and-custom-feeds.md) compares the two.

## The problem it solves

Public records are published office by office. Each office picks its own columns, its own file format, its own way of writing a parcel number and its own schedule. Getting one county's building permits into a single table can mean reading eight permit offices, each with a different export.

If your product needs one parcel table and one permit table, with each permit pointing at its parcel, someone has to do this work:

* **Map every source to your columns.** One office calls it `job_value`, another `est_cost`, a third leaves it out.
* **Match records across sources.** Permits rarely carry the parcel's id in the form the parcel dataset uses. Some carry only an address.
* **Find out what you'll actually get.** You usually learn that a column is half empty after you have built the pipeline for it.
* **Do it again.** Every time an office changes its export, and for every county you add.

That is a data pipeline per county, and a team to keep it running. It is also work that has nothing to do with what your product is for.

A custom feed moves that work to Ploti. You describe the tables once. Ploti's agents map the sources, match the records, tell you how filled each column will be before you commit to anything, and redo the work whenever a source changes. Your system loads tables that already fit.

## How it works

You ask for a custom feed in the Ploti app, under **Data Feeds**, with **Custom feed**. A workspace admin asks for and creates custom feeds, in a workspace with an active Ploti plan. Every member can read the request and its proposal.

**1. Describe what you need**

Say it in your own words: the places, what one row is, and the columns you
want. You don't need to know which datasets exist.

**2. Ploti checks what it holds**

Ploti's agent reads the datasets it holds for those places, counts the
records and measures how filled each column is. For anything missing, it
finds which public body publishes it. This takes a few minutes, and the page
shows each step. If your description is too vague to check, it asks a few
short questions first.

**3. Read the proposal**

The proposal says what Ploti has today, what it would need to collect, and
the feed or feeds it would build, column by column.

**4. Reply to change it**

Ask for a column to be added or dropped, a different row, or other places.
Each reply gets a new, complete proposal that replaces the last.

**5. Create the feeds**

When the proposal is right, create the feeds. Ploti starts
collecting each missing source, and the page shows where each one stands.

## An example

A site-selection product has a parcel table and a permit table, and each permit row must point at its parcel. Its team writes:

> Every parcel in Orange County, Florida with its owner name, site address, zoning district and last sale price, and every building permit issued on those parcels with its type, issue date and job value. I want to keep both in my own database and tie each permit to its parcel.

Ploti proposes two feeds:

* **Orange County parcels**, one row per parcel. Ready today: the county's parcel dataset holds 494,832 parcels, with owner and site address on every one, a zoning district on 88% and a last qualified sale on 87%.
* **Orange County building permits**, one row per permit, with a `parcel_ploti_id` column holding the record id of the permit's parcel. Not held yet: the county and its cities each run their own permit office, so Ploti would collect each office's records.

The team replies "Add the flood zone each parcel is in." The next proposal adds a `flood_zone` column to the parcel feed, filled from the FEMA flood map Ploti holds for the county, and leaves the rest as it was.

## Reading a proposal

### What Ploti has today

The kinds of data Ploti already holds for the request, each with the datasets behind it and how much of your places it reaches, such as "1 of 1 county" or "3 of 4 counties".

### What Ploti would need to get

Each source Ploti would have to collect. Ploti always collects the whole source, such as every building permit a city has published, and not only the slice your feed uses. The dataset then stays in Ploti, keeps updating, and is open to your workspace as a dataset of its own.

Collecting a dataset costs 3 credits, charged only when it is collected and returned if it can't be found. One request can need several: a county where eight offices issue permits is eight datasets. The proposal lists each one before you create anything. [Coverage areas and pricing](https://ploti.ai/docs/getting-started/coverage-areas.md#credits) says how credits work.

### Coverage areas

A grid of the places in your request against the kinds of data, each cell marked ready, partial or not held. A place outside your workspace's coverage areas is marked, with a way to add it. A feed delivers only places your coverage areas include.

### Proposed feeds

Each feed says what one row is, and lists its columns. For each column:

| Field | What it tells you |
| - | - |
| **Today** | How much of it Ploti holds now, such as "100% of parcels" or "None" |
| **Prediction** | How likely it is to be filled once every source has arrived |
| **Why** | The evidence, naming the dataset and the source's own column |
| **Basis** | Whether Ploti read it in its own data, confirmed it by a search, or is going on what such sources usually carry |

A prediction is one of four:

| Prediction | Meaning |
| - | - |
| **Have it** | Ploti holds it and it is filled today |
| **Likely** | The sources Ploti would collect normally carry it |
| **Uncertain** | Some sources carry it and others don't, or its values differ from place to place |
| **Unlikely** | Ploti found no public source for it |

A column you asked for stays in the proposal even when it is unlikely, so you can see what you would not get. Ploti may add a column you did not ask for when the feed can't be used without it, such as an address, and says so.

## One row is one thing

Ploti proposes the fewest feeds that deliver what you asked for without flattening it. A parcel can have many permits, so "parcels with their permits" is two feeds, not one parcel feed with a permit count. Each feed then reports its own added, changed and removed rows.

If you would rather have one flat table, such as each parcel with its latest permit, say so in a reply.

## How feeds tie together

Every feed's first column is `_ploti_record_id`, Ploti's id for the row. It stays with the record from one version to the next, so it is the column to key your table on. [Record ids](https://ploti.ai/docs/feeds/record-ids.md) says what it promises.

When a row of one feed belongs to a row of another, it carries that row's record id in a column named for what it points at:

| Feed | Column | Holds |
| - | - | - |
| Building permits | `parcel_ploti_id` | The `_ploti_record_id` of the permit's parcel |

Feeds are tied by record id and never by a source's own key. A parcel number can change, repeat or be written differently by two offices. The record id does not, so the link holds when everything else about the record changes. You can still receive the source's keys as ordinary columns.

To fill a link, Ploti matches the two sources' records. It uses a number both carry when there is one, the name and address when there is not, and the record's place on the map when it has a location. The column's prediction says which, and how complete the match is expected to be. A row Ploti can't match has an empty link, and is still delivered.

## After you create the feeds

The request's page lists each source being collected and where it stands. Collecting can take hours or days, and longer when a public body has to be asked for the records. A feed's rows for a place arrive once the sources it is built from have.

A feed built only from data Ploti already holds needs no collecting.

Each custom feed is delivered like any other dataset in Data Feeds: a snapshot to load once, then a changes file for each new version, with the same [envelope columns](https://ploti.ai/docs/feeds/versions-and-changes.md#envelope-columns). When a source changes, Ploti rebuilds the feed and sends what changed.

## What is not promised

* **That every column fills.** A prediction is Ploti's estimate before the sources arrive. The delivered feed can differ, and its fill is measured once it is built.
* **That every link is found.** A permit with no parcel number and an address Ploti can't place has no link to a parcel.
* **Data Ploti can't collect.** When no public body publishes a source, or it refuses to release it, the columns that depended on it stay empty.
* **A schema that never changes.** You set a custom feed's columns, so they don't move when a source's do. A source that drops a column the feed is built on leaves that column empty from then on.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.