Permit rows for a program, with no account. Call the API with no key. It answers 402 Payment Required with the price and where to pay. Your wallet signs the payment, you call again with it in the X-PAYMENT header, the facilitator settles it in USDC on Base, and the rows come down with the receipt in X-PAYMENT-RESPONSE. The standard is x402.
Machine-readable: /.well-known/x402.json and /llms.txt. A key instead of a payment: whitetape.io/#key, ten rows free a month.
GET https://api.monarcbuild.com/permits/search?q=anne%20arundel&state=MD
Numbers per jurisdiction, never a row: permits in the last 30 and 90 days, all on file, the dollars of work, the newest date, the portal the county runs, and get_rows, the address for the rows. Only areas we hold are listed.
GET https://api.monarcbuild.com/permits?jurisdiction_id=166362&issue_date_from=2026-07-29&limit=100
With no key you get:
HTTP 402
{
"x402Version": 1,
"accepts": [{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "3000000",
"resource": "https://api.monarcbuild.com/permits",
"description": "White Tape: up to 100 permit rows at 3 cents a row",
"payTo": "0x…",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"maxTimeoutSeconds": 60
}]
}
maxAmountRequired is in USDC's six decimals: 3,000,000 is $3.00, which is 100 rows at 3 cents. limit sets the rows and so the price; the most is 1,000 rows, $30.00.
GET https://api.monarcbuild.com/permits?jurisdiction_id=166362&issue_date_from=2026-07-29&limit=100 X-PAYMENT: <the x402 payment payload, base64>
Any x402 client does the signing: the x402 packages for Python and TypeScript, or Coinbase's agent kit. The response carries the rows and X-PAYMENT-RESPONSE with the settlement.
| key | type | what |
|---|---|---|
| jurisdiction_id | string | the Census id of the issuing government |
| permit_number | string | the office's own number |
| permit_type | string | the office's type, as it names it |
| permit_status | string | issued, finaled, closed, as it names it |
| description | string | the work, in the office's words |
| parcel_id | string | the parcel, however the county keys it |
| address, city, state, zip | string | the job site |
| owner_name, applicant_name, contractor_name, contractor_license, contractor_phone | string | where the county publishes them; empty where it does not |
| value, fee | number | dollars |
| applied_date, issue_date, expire_date, final_date | date | YYYY-MM-DD |
| use_type, square_feet, units, latitude, longitude | string, number | where published |
| source_file, read_on | string, date | the file the row came from and the day it was read |
| source_extra | object | every source column that matched no key, as it came, flagged |
The full schema with the condense rule: /schema.json.
jurisdiction_id | one government, from the search |
state | two letters |
permit_type | matched loosely, case does not matter |
issue_date_from, issue_date_to | YYYY-MM-DD |
value_min | dollars |
limit | 1 to 1,000 rows; sets the price |
One visit a second per wallet. Rows are public records and may be stored and resold. Nothing on a row is private; where a county publishes an owner's name we serve it, and where it does not we do not. Questions to hello@whitetape.io.