Developer portal
Pamm Properties API
A public, unauthenticated REST API for the commercial lease inventory of PAMM Family Properties LLC in McAllen, Mission, Pharr, and Edinburg, Texas. Read the portfolio, check live availability with rent and square footage, and submit a leasing inquiry.
Quickstart
Three requests, no setup. Every endpoint is public, so there is nothing to install and no key to obtain before the first call.
1. Confirm the API is reachable
curl https://www.pammproperties.com/api/health2. List the properties
curl "https://www.pammproperties.com/api/properties?type=Retail&limit=5"Returns { "count": n, "data": [...] }. Each item carries the property id, street address, square footage, space type, listing status, coordinates, and the canonical page URL.
3. Read live availability with rent
curl "https://www.pammproperties.com/api/spaces?maxRent=3000&minSqft=1200"4. Send a leasing inquiry
curl -X POST https://www.pammproperties.com/api/contact \
-H "Content-Type: application/json" \
-d '{
"firstName": "Maria",
"lastName": "Gonzalez",
"email": "maria@example.com",
"phone": "+1 956 555 0142",
"message": "Looking for 1,500 SF of retail space in McAllen starting in January.",
"smsConsent": true
}'This one reaches a human. Only send it for a real prospect who supplied their own details. smsConsent is optional — set it to true only if that person explicitly agreed to receive text messages, and omit it otherwise.
Authentication and API keys
There are none, by design.
- No API key is required. Do not send an Authorization header. Requests carrying one are accepted and the credential is ignored.
- No OAuth, no signup, no sandbox key. The same URLs serve production data to everyone.
- CORS is open. Every JSON response sends
Access-Control-Allow-Origin: *, so browser clients can call the API directly. - If your organization later needs a keyed, higher-volume feed, email jgonzalez@pammproperties.com.
Endpoints
Version 1.0.0. Every operation below is described in full, with typed parameters and response schemas, in the OpenAPI 3.1 document.
| Operation | Method | Path | What it does |
|---|---|---|---|
listApiEndpoints | GET | /api | List every public endpoint |
getApiHealth | GET | /api/health | Check API availability |
listProperties | GET | /api/properties | List commercial properties for lease or sale |
getPropertyById | GET | /api/properties/{propertyId} | Get one property by id |
listAvailableSpaces | GET | /api/spaces | List currently available suites with rent and size |
submitLeasingInquiry | POST | /api/contact | Send a leasing inquiry to a leasing agent |
Machine-readable contract: /openapi.json and /openapi.yaml. Both are also served under /api/openapi.json and /api/openapi.yaml.
Sandbox
The read endpoints are the sandbox. They are side-effect free, cost nothing to call, and return the same data every client sees.
GET /api/healthis the connectivity probe. Use it while wiring up a client instead of posting a test inquiry.GET /api,GET /api/properties,GET /api/properties/{id}, andGET /api/spacesare safe and idempotent. Call them as often as you need.POST /api/contactis the only operation with a side effect: it notifies a human leasing agent. There is no test mode. Do not use it for smoke tests.
Errors
Every failure under /api returns the same JSON envelope with the same media type. No endpoint ever answers with an HTML error page.
{
"error": {
"code": "not_found",
"message": "No property exists with id 999.",
"hint": "Call GET /api/properties to list every available property and its id.",
"status": 404,
"documentation_url": "https://www.pammproperties.com/developers"
}
}Branch on error.code, never on the message text. The codes are stable:
| Code | HTTP | Raised when |
|---|---|---|
bad_request | 400 | A query parameter or the JSON body was malformed. |
validation_error | 400 | The body parsed but failed the schema. A details array names each invalid field. |
not_found | 404 | The path or the record does not exist. |
method_not_allowed | 405 | The endpoint exists but not for that verb. An Allow header lists the valid ones. |
unsupported_media_type | 415 | A write request was not sent as application/json. |
upstream_unavailable | 503 | The live availability database could not be reached. |
internal_error | 500 | Anything unexpected. Safe to retry once. |
CLI
The pamm command-line tool wraps the same endpoints, so a script or an agent can query the portfolio without writing an HTTP client.
Run it without installing
npx @pammproperties/cli properties --type Retail --limit 5Install globally
npm install -g @pammproperties/cli
pamm spaces --max-rent 3000
pamm property 1 --jsonCommands
pamm properties— list the portfolio, with--type,--listing-type,--location,--query, and--limit.pamm property <id>— one property in full.pamm spaces— live availability, with--max-rentand--min-sqft.pamm openapi— print the OpenAPI document.pamm health— check the service.
Every command takes --json for machine-readable output. Source: github.com/capitalcodecolmx/pamm.
AI agents and MCP
The site is built to be read by software as well as by people.
- /llms.txt summarizes the site for a model: what it is for, when not to use it, the full listing table, and the developer resources on this page.
- Every HTML page also answers in Markdown. Send
Accept: text/markdownto any URL and you get clean prose instead of markup. - The OpenAPI document is written for function calling: unique
operationIdvalues, a description on every operation and parameter, typed schemas, and declared response bodies for both success and failure. Feed it straight into a tool-calling loop. - No page requires JavaScript execution, a login, or a paywall to read.
curl -H "Accept: text/markdown" https://www.pammproperties.com/available-spacesRate limits and support
No published quota. Be reasonable and cache what you read.
- Read endpoints send a
Cache-Controlheader with an edge lifetime. Respect it rather than polling. - Availability data changes daily. Refresh
/api/spacesno more than once a minute. - Questions, bug reports, or a request for higher volume: jgonzalez@pammproperties.com or +1 (956) 369-9487.
- Use of the API is governed by the Terms of Service and the Privacy Policy.