White Tape · for agents

The 402 door.

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.

1. Find what we hold, free

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.

2. Ask for the rows

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.

3. Pay and call again

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.

The row

keytypewhat
jurisdiction_idstringthe Census id of the issuing government
permit_numberstringthe office's own number
permit_typestringthe office's type, as it names it
permit_statusstringissued, finaled, closed, as it names it
descriptionstringthe work, in the office's words
parcel_idstringthe parcel, however the county keys it
address, city, state, zipstringthe job site
owner_name, applicant_name, contractor_name, contractor_license, contractor_phonestringwhere the county publishes them; empty where it does not
value, feenumberdollars
applied_date, issue_date, expire_date, final_datedateYYYY-MM-DD
use_type, square_feet, units, latitude, longitudestring, numberwhere published
source_file, read_onstring, datethe file the row came from and the day it was read
source_extraobjectevery source column that matched no key, as it came, flagged

The full schema with the condense rule: /schema.json.

Filters

jurisdiction_idone government, from the search
statetwo letters
permit_typematched loosely, case does not matter
issue_date_from, issue_date_toYYYY-MM-DD
value_mindollars
limit1 to 1,000 rows; sets the price

Rules

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.