# DoorProfit API — Agent Quickstart

DoorProfit is a REST API and hosted MCP server for U.S. location data: crime safety grades and nearby incident counts, neighborhood demographics, and registered offenders. Input is a street address or lat/lng. Output is JSON.

- Base URL: `https://api.doorprofit.com/v1/`
- MCP server: `https://api.doorprofit.com/mcp` (OAuth or API key)
- Full HTML docs: https://api.doorprofit.com/docs/
- Pricing: https://api.doorprofit.com/billing
- Sign up (free key, no card): https://api.doorprofit.com/signup
- Support: support@doorprofit.com

There is no SDK or CLI to install. Any HTTP client works.

## 1. Get an API key

1. Sign up at https://api.doorprofit.com/signup (email or Google). The free plan includes 10 API calls per month.
2. Copy the key from https://api.doorprofit.com/dashboard.
3. Keep it server-side (environment variable). Do not ship it in client code.

Prerequisite and auth boundary: every `/v1/*` call needs a key. Without one the API returns HTTP 401 `INVALID_API_KEY`. Signup is done by a human in a browser; an agent cannot create a key on its own.

**No key yet? Use the demo key.** `key=demo` works with no signup, but only for the test address `500 Main St, Dallas, TX 75202` (or `lat=32.78014&lng=-96.800454`), on `/v1/crime`, `/v1/neighborhood`, `/v1/offenders` (location search), `/v1/usage`, and the MCP server. Any other location, name searches, and the embed widget return 403 `DEMO_KEY_TEST_ADDRESS_ONLY`. With a real key, the test address also never consumes quota.

## 2. First call

```bash
curl "https://api.doorprofit.com/v1/crime?address=500+Main+St+Dallas+TX+75202&key=demo"
```

Then swap in your own key for any U.S. address:

```bash
export DOORPROFIT_API_KEY=your_key_here
curl "https://api.doorprofit.com/v1/crime?address=1600+Main+St+Houston+TX&key=$DOORPROFIT_API_KEY"
```

```json
{
  "success": true,
  "location": { "address": "500 Main St, Dallas, TX 75202, USA", "city": "Dallas", "state": "TX", "zipcode": "75202", "lat": 32.78014, "lng": -96.800454 },
  "crime_score": "C+",
  "crime_numeric": 0.21,
  "crime_score_source": "incidents",
  "crime_description": "Higher than average crime",
  "incidents": { "radius_feet": 1000, "date_from": "2025-04-01", "date_to": "2026-04-01", "count": 245, "by_type": { "assault": 74, "theft": 109, "vandalism": 39 } }
}
```

## 3. Endpoints

All are `GET`. Auth is the `key` query parameter. Location is either `address` (URL-encoded) or `lat` + `lng`.

| Endpoint | Returns | Cost |
|---|---|---|
| `/v1/crime` | `crime_score` (A+ safest … F), `crime_numeric` (0–1, lower is safer), `crime_description`, `incidents` (counts within 1,000 ft by type, or `null` where the city has no incident data) | 1 call |
| `/v1/neighborhood` | `neighborhood.name`, `demographics`, `income`, `housing`, `education`, `cost_of_living` (100 = national avg), `rent` (median, by bedroom), `weather`, `natural_disaster_risk` | 1 call |
| `/v1/offenders` | Registered offenders: `name`, `address`, `lat`/`lng`, `distance` (miles), `photo`, `offense`, `offenses[]`, `risk_level`, `source_url`, plus `total_count`, `page`, `total_pages` | 1 call per page |
| `/v1/usage` | Plan, monthly/daily limits used and remaining, overage | Free |

`/v1/offenders` parameters:

- By location: `address` or `lat`+`lng`, optional `radius` in miles (default 1, max 3).
- By name: at least one of `first_name`, `last_name`, `dob` (`YYYY-MM-DD`), optionally narrowed by `city`, `state` (2-letter), `zipcode`. City/state/ZIP alone are not accepted. If location parameters are also sent, location search wins.
- Pagination: `page` (default 1), `limit` (default 50, max 100).

```bash
curl "https://api.doorprofit.com/v1/neighborhood?lat=32.778635&lng=-96.807295&key=$DOORPROFIT_API_KEY"
curl "https://api.doorprofit.com/v1/offenders?address=500+Main+St+Dallas+TX+75202&radius=2&key=$DOORPROFIT_API_KEY"
curl "https://api.doorprofit.com/v1/offenders?last_name=Smith&state=TX&key=$DOORPROFIT_API_KEY"
curl "https://api.doorprofit.com/v1/usage?key=$DOORPROFIT_API_KEY"
```

Python:

```python
import os, requests

r = requests.get(
    "https://api.doorprofit.com/v1/crime",
    params={"address": "500 Main St Dallas TX 75202", "key": os.environ["DOORPROFIT_API_KEY"]},
    timeout=30,
)
r.raise_for_status()
data = r.json()
print(data["crime_score"], data["crime_description"])
```

JavaScript:

```javascript
const params = new URLSearchParams({ address: "500 Main St Dallas TX 75202", key: process.env.DOORPROFIT_API_KEY });
const res = await fetch(`https://api.doorprofit.com/v1/crime?${params}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
console.log(data.crime_score, data.incidents?.count);
```

## 4. MCP server (Claude, ChatGPT, Cursor, other agents)

URL: `https://api.doorprofit.com/mcp` (Streamable HTTP, JSON-RPC).

Tools: `get_crime_data`, `get_neighborhood_data`, `search_offenders` (1 API call each), `get_api_usage` (free).

- OAuth (easiest): add the URL to any OAuth-capable MCP client. The user logs in to DoorProfit and approves. Discovery: `https://api.doorprofit.com/.well-known/oauth-authorization-server`.
- API key:

```json
{
  "mcpServers": {
    "doorprofit": {
      "url": "https://api.doorprofit.com/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}
```

Clients that only accept a URL: `https://api.doorprofit.com/mcp?key=YOUR_API_KEY`. MCP calls use the same quota as REST calls.

## 5. Embeddable crime map widget

```html
<div id="doorprofit-crime-map" data-address="500 Adams St, Tulsa, OK" data-key="YOUR_API_KEY"></div>
<script src="https://api.doorprofit.com/v1/embed/crime-map.js" async></script>
```

Optional: `data-lat`/`data-lng` instead of `data-address`, `data-zoom` (default 13), `data-height` (default `400px`). Billed as embed views (one per unique visitor per month, bots excluded), separate from API calls. The "Crime data by DoorProfit" attribution must stay visible. Restrict a key to your domains in the dashboard ("Allowed domains").

## 6. Pricing

Billed monthly. Free plan has no overage (requests stop at the limit); paid plans bill overage instead of blocking.

| Plan | Price | API calls / month | Daily limit | Rate limit | Embed views / month | API overage |
|---|---|---|---|---|---|---|
| Free | $0 | 10 | 50 | 2 req/s | 5,000 | none |
| Starter | $25/mo | 300 | 1,500 | 5 req/s | 50,000 | $0.15/call |
| Growth | $50/mo | 600 | 3,000 | 10 req/s | 200,000 | $0.10/call |
| Pro | $100/mo | 1,200 | 6,000 | 20 req/s | 500,000 | $0.08/call |
| Enterprise | custom | custom | custom | custom | custom | support@doorprofit.com |

Embed overage on paid plans: $0.50 per 1,000 views. Overage is charged at a $25 threshold or at the end of the billing period.

Every response carries `X-Monthly-Limit`, `X-Monthly-Remaining`, `X-Daily-Limit`, `X-Daily-Remaining`, `X-RateLimit-Limit`, `X-Plan`.

## 7. Errors

```json
{ "success": false, "error": { "code": "INVALID_API_KEY", "message": "The API key provided is invalid or has been revoked.", "documentation_url": "https://api.doorprofit.com/docs/#authentication" } }
```

| HTTP | Code | Meaning |
|---|---|---|
| 400 | `MISSING_PARAMETER`, `INVALID_COORDINATES`, `INVALID_ADDRESS` | Missing or invalid parameters, or the address could not be geocoded |
| 401 | `INVALID_API_KEY` | Key missing, invalid, or revoked |
| 402 | `ACCOUNT_BLOCKED` | Payment failed; update billing in the dashboard |
| 403 | `QUOTA_EXCEEDED` | Monthly quota used up on a plan without overage (Free). Upgrade to continue |
| 403 | `DOMAIN_NOT_ALLOWED` | Embed request from a domain not on the key's allowlist |
| 403 | `DEMO_KEY_TEST_ADDRESS_ONLY` | `key=demo` used for a location other than the test address |
| 429 | `RATE_LIMIT_EXCEEDED`, `DAILY_LIMIT_EXCEEDED` | Per-second or daily limit hit; back off and retry |
| 500 | — | Server error |

## 8. Data

Crime grades come from FBI UCR/NIBRS and local law enforcement data, scored at the census-block level from reported incidents where a city publishes them and from block-group statistics elsewhere. Crime data updates daily, offender data weekly, demographics with U.S. Census releases. Coverage: all 50 states. Commercial use is included on paid plans.
