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.
A network fault can lose an answer after the write went through. So every POST this page lists takes an Idempotency-Key header, and a repeat with the same key is safe. The API runs the write once and answers the same body to every repeat.

Which requests take the key

  • The seller’s creating and moving posts: POST /sell/drafts, POST /sell/drafts/{draft_id}/publish, POST /sell/deals/{deal_id}/status, POST /sell/deals/{deal_id}/offers, POST /sell/deals/{deal_id}/leads, POST /sell/buyers/{buyer_id}/strikes and POST /sell/reviews/{review_id}/response.
  • The seller’s answers to an offer and to an address request: POST /sell/offers/{offer_id}/accept, /decline and /counter, and POST /sell/inquiries/{inquiry_id}/approve and /decline.
  • The buyer’s writes: POST /buy/offers, POST /buy/offers/{offer_id}/counter, /decline, /accept and /withdraw, POST /buy/deals/{deal_id}/inquiries, POST /buy/buy-boxes and POST /buy/me/proof-of-funds.
  • The webhook endpoints of both sides, POST /sell/webhooks and POST /buy/webhooks.
The reference lists 409 idempotency_conflict and 409 idempotency_in_progress on each of these operations, and on no other operation. A preview (POST .../offers/preview, POST .../counter/preview) writes nothing and takes no key. An upload ticket writes nothing. A media post (POST .../media) and a document post (POST .../documents) take no key. A repeat adds the same staged file a second time, so send each staged key once. POST /sell/deals/{deal_id}/reassign and the webhook test posts (POST .../webhooks/{webhook_id}/test) take no key. A PATCH sets a state and takes no key. One of the posts in the list above without the header answers 400 invalid_parameter with parameter: "Idempotency-Key".

The key

  • 1 to 255 characters. Use a UUID, or a key of your own system, for example your record id and the action.
  • Scoped to your OAuth client and to the person the token names. The same string from another client or another person is another key.
  • Kept 24 hours. After that, the same string starts a new request.
  • Stored with a fingerprint of the method, the path and the body. The order of the keys inside the JSON does not change the fingerprint.

Replay and the two conflicts

The API checks your authorization again before a replay. The replayed body is the first answer, byte for byte, so its meta.request_id is the first request’s. The X-Request-Id header is the new request’s.

The domain rules

Beyond the key, three rules of the domain refuse a duplicate:
  • One active deal per property. A second publish on an address with a live deal answers 409 address_unavailable.
  • One active chain per buyer per deal. A second submit answers 409 offer_exists, and the body names the open round.
  • One inquiry per type per deal per day. The second inquiry, or the second address request, on one deal in 24 hours answers 429 duplicate_inquiry with Retry-After: 86400, and the body names deal_id and type.
A repeat of a counter on a round that closed answers 409 offer_superseded, with a key or without one.

A retry recipe

1

Mint the key before the first send

Make the key once and store it with the intent, then send. A key made after a failure protects nothing.
2

Repeat the same request on a network fault or a 5xx

Same method, same path, same body, same key. Wait 1, 2, 4 and 8 seconds between tries. Stop after five tries and raise an alert with the key.
3

Read the answer

A 2xx with Idempotent-Replayed: true is the first answer again. On 409 idempotency_in_progress, wait Retry-After, then repeat. On 409 idempotency_conflict, stop: your body changed between tries. On any other 4xx, change the request and use a new key.
Node.js
Errors has both conflict codes. Identifiers and the envelope has the request id.