Skip to main content
The Marketplace API is in a private beta. It answers only for accounts Investorlift has enabled. Access says how to ask for one. A route shape on these pages can change before the beta ends. The changelog records every change.
Every resource of the Marketplace API follows the same conventions, and this page states them once. The God Mode envelope has the same three top-level keys. The ids, the money rule and the status rule are the marketplace’s own.

Identifiers

A public id is the row id with a type prefix and an underscore, for example mdl_a1b2c3d4e5f6. The prefix says what the id names. Store the id whole, prefix included, and send it back as the API served it. The id encodes its creation instant, so ids sort in creation order. Every deal, draft, offer, inquiry, lead, buy box and webhook endpoint also carries created_at. A lead has no id of its own. The route addresses it by its deal and its buyer: /sell/deals/{deal_id}/leads/{buyer_id}. Some ids carry no prefix. A media item and a document carry a plain id, which has a meaning only inside their draft or their deal. client_id names an OAuth client, and agreement.id names an agreement. Store them as strings. An id of the wrong form answers 400 invalid_id. An id of the right form that names nothing your account owns answers 404 not_found. The API does not tell a foreign id from an unknown one. The God Mode API uses other prefixes (deal_, prop_, inv_), and an id never crosses the two APIs.

Values

  • Money is a whole number of US dollars, never a float and never cents: asking_price, offer_amount, emd_amount.
  • Timestamps are RFC 3339 strings in UTC, for example 2026-10-02T14:03:00Z. A deal, a draft, an offer, an inquiry, a lead, a buy box and a webhook endpoint carry created_at and updated_at.
  • Null means not entered. A null entity_name says the buyer linked no legal entity.
  • A field you cannot see is absent, never null. A token without contacts:read gets no email key on a buyer block. Test for the key, and your code tells “not allowed” from “not entered”. One exception: a recommended lead carries buyer: null until the person acts, because the key is part of every lead row. Read origin to tell the two apart.
  • A hidden address is address: { status: "hidden", city, state, zip } with street absent. Its coordinates sit on a coarse grid, and is_approximate is true. Once the seller shares the street, status reads approved and street appears. On the deal read, status also reads requested after your address request, and declined after the seller declines it. A search row carries hidden or approved only.

The envelope

One resource answers { data, meta }. A list answers { data, page, meta }. This is a page of one row:
Every response also carries the request id as the X-Request-Id header, and every problem body carries it as request_id. Log it, and quote it to support. A webhook endpoint pins api_version at create (Webhooks and events).

Compatibility

/marketplace/v1 is additive. A new field, a new enum value or a new event type arrives without notice, and your client ignores what it does not know. A removal or a rename gets 30 days of email notice and a line in the changelog. api_version is the date of the contract. A webhook endpoint pins it at create. A payload change ships as a new date, and you opt into it with a new endpoint.

Pagination

Ask for a page. Read page.next_cursor. Send it back as cursor= with the same query. If it is null, stop. A short page is not the end of the list. Only a null cursor is. The cursor is opaque. The API binds it to your account and to the query. A cursor from another account, another query or another list answers 400 invalid_parameter with parameter: "cursor". Read the first page again. The events feed is the one exception, because its cursor is a sequence position and a changed types= keeps it valid (Webhooks and events). A page carries 25 rows by default. Where a list takes limit=, the parameter sets the page size, up to 100 rows. The two lead lists and the seller’s inquiry list serve 100 rows by default. A buyer’s own offers list and own inquiries list take at most 25 rows. The deal search and the two review lists take no limit= and serve 25 rows. The two events feeds serve 50 rows by default. updated_since= is the sync primitive. The lists that take it sort by updated_at, newest first, then by id. Keep the updated_at of the newest row you stored. On the next run, send it as updated_since=, and the list carries only the rows that changed after that instant. Page through with the cursor as usual. Do not compute a page count: the API never counts the whole set for you.

The status rule

The two webhook test posts also answer 202. Their data names the ping event, and nothing is on hold. Errors lists every code with its recovery sentence. Trust and limits explains the hold queue.