GCMGM.com Partner API
Version v1. Push property and land records to GCMGM.com, where builders and contractors see them as leads and submit proposals.
Getting started
Your GCMGM.com contact will issue you an API key (it looks like cp_live_…). Send it on every request:
Authorization: Bearer cp_live_…
- Base URL:
https://www.gcmgm.com/api/v1/partner/v1 - Rate limit: 120 requests per minute per API key. A separate 600/minute per-IP ceiling also applies (including to requests with a missing or invalid key).
- Leads are keyed by your externalId. POSTing the same externalId again updates the existing lead (and re-opens it if it was closed) rather than creating a duplicate — so retries are safe.
Testing. Ask us for a sandbox key to develop against. It behaves identically to a live key on every endpoint, but its leads are never shown to builders — so you can push, re-push and delete freely without anyone seeing test properties. Switch to your live key when you are ready to go live.
POST/api/v1/partner/v1/leads
Create or update a property lead
Push a property or land record. Idempotent on externalId: the first call creates (201), subsequent calls update (200).
| externalId | string (1–80) | required | Your unique id for this record. It becomes a URL path segment on GET and DELETE, so percent-encode it there if it contains /, ? or #. |
| address | string (1–240) | required | Street address of the property. |
| title | string (≤200) | optional | Short headline; defaults to the address in the UI. |
| city | string (≤120) | optional | City. |
| state | string (≤120) | optional | State / region. |
| postalCode | string (≤20) | optional | Postal / ZIP code. |
| propertyType | string (≤80) | optional | Your own type label (e.g. land, single-family). |
| description | string (≤4000) | optional | Free-text details for the builder. |
| lotSizeSqft | integer (0–1000000000) | optional | Lot size in square feet. |
| budgetCents | integer (0–2147483647) | optional | Budget in cents (e.g. 25000000 = $250,000). Max is ~$21.5M. |
| attributes | object | optional | Any extra key/values, stored verbatim. Not echoed back in responses. |
| id | string | required | GCMGM.com's id for the lead. |
| externalId | string | required | Your id for the record (echoed back). |
| status | string | required | "OPEN" or "CLOSED". |
| receivedAt | string (ISO 8601) | required | When first received. |
| updatedAt | string (ISO 8601) | required | When last updated. |
| result | string | required | "created" or "updated". |
curl -X POST "https://www.gcmgm.com/api/v1/partner/v1/leads" \
-H "Authorization: Bearer cp_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"externalId": "LOT-48821",
"title": "1.2-acre residential lot",
"address": "4200 Bee Cave Rd",
"city": "Austin",
"state": "TX",
"postalCode": "78746",
"propertyType": "land",
"description": "Cleared corner lot, utilities at street. Owner ready to build.",
"lotSizeSqft": 52272,
"budgetCents": 45000000,
"attributes": {
"zoning": "SF-2",
"ownerContact": "listed agent"
}
}'GET/api/v1/partner/v1/leads
List your leads
Every lead you have pushed, newest first — for reconciling your records against ours. Cursor-paginated: pass the nextCursor from the previous response to fetch the next page, and stop when it is null.
| status | "OPEN" | "CLOSED" | optional | Filter by state. Omit for both. |
| updatedSince | string (ISO 8601) | optional | Only leads changed at or after this time — use it for incremental syncs. |
| cursor | string (uuid) | optional | The nextCursor from the previous page. |
| limit | integer (1–200) | optional | Page size. Defaults to 50. |
| leads | array of Lead | required | This page of results. See the Lead table below. |
| nextCursor | string | null | required | Pass as cursor for the next page. null means you have reached the end. |
| id | string | required | GCMGM.com's id for the lead. |
| externalId | string | required | Your id for the record (echoed back). |
| status | string | required | "OPEN" or "CLOSED". |
| receivedAt | string (ISO 8601) | required | When first received. |
| updatedAt | string (ISO 8601) | required | When last updated. |
| proposalCount | integer | required | How many proposals builders have submitted on this lead. |
curl -X GET "https://www.gcmgm.com/api/v1/partner/v1/leads?status=OPEN&limit=50" \ -H "Authorization: Bearer cp_live_YOUR_KEY"
GET/api/v1/partner/v1/leads/:externalId
Fetch a lead and its proposals
Returns the current lead plus any proposals builders have submitted.
| id | string | required | GCMGM.com's id for the lead. |
| externalId | string | required | Your id for the record (echoed back). |
| status | string | required | "OPEN" or "CLOSED". |
| receivedAt | string (ISO 8601) | required | When first received. |
| updatedAt | string (ISO 8601) | required | When last updated. |
| proposals | array of Proposal | required | Every proposal builders have submitted, newest first. See the Proposal table below. |
| company | string | required | Name of the builder company that submitted it. |
| message | string | required | The builder's pitch. |
| amountCents | integer | null | optional | Proposed amount in cents. null when the builder did not quote a figure. |
| status | "PENDING" | "WITHDRAWN" | "ACCEPTED" | "REJECTED" | required | WITHDRAWN proposals are still returned — filter them out if you only want live bids. |
| submittedAt | string (ISO 8601) | required | When the proposal was created. |
curl -X GET "https://www.gcmgm.com/api/v1/partner/v1/leads/LOT-48821" \ -H "Authorization: Bearer cp_live_YOUR_KEY"
DELETE/api/v1/partner/v1/leads/:externalId
Close a lead
Marks the lead CLOSED so builders can no longer propose on it. The record and its proposals are retained; nothing is hard-deleted.
| id | string | required | GCMGM.com's id for the lead. |
| externalId | string | required | Your id for the record (echoed back). |
| status | string | required | "OPEN" or "CLOSED". |
| receivedAt | string (ISO 8601) | required | When first received. |
| updatedAt | string (ISO 8601) | required | When last updated. |
curl -X DELETE "https://www.gcmgm.com/api/v1/partner/v1/leads/LOT-48821" \ -H "Authorization: Bearer cp_live_YOUR_KEY"
Errors
| 400 | Request body failed validation — see the issues object. Also returned for malformed JSON. |
| 401 | Missing or invalid API key. |
| 404 | No lead with that externalId for your account. |
| 413 | Request body too large. |
| 429 | Rate limit exceeded — retry after the Retry-After header. |
| error | string | required | Machine-readable slug, e.g. "validation_error", "unauthorized", "rate_limited". |
| message | string | required | Human-readable explanation. |
| issues | object | optional | Present on 400 validation failures: Zod's flattened fieldErrors / formErrors. |