Documentation

GET /api/offer

The researched offer for the session's product, or the refusal that says why there is none.

RequestGET /api/offer
AuthenticationSession cookie required
Handlerbackend/server.py

What it does

Resolves the product the same way `/api/ad` does — claimed first, then the hold, never a direct read of the holds table. A product with no research row is not 'no viable offer'; it is `not_yet_researched`, and collapsing the two would let an unrun script report itself as a market conclusion. The fairness disclosure and the freshness line are computed at serve time rather than stamped at generation, because a property of price and product belongs where it is read: stamping it at generation left the longest-standing offers without it. A price the engine would no longer stand behind is refused with `failed_leg: "pricing"` rather than served.

Authentication

Session cookie required. Send the ff_session cookie. Without one the engine treats the caller as a new visitor with no holds and no claims, and returns a new cookie to use from then on.

Parameters

ParameterInTypeRequiredDescription
ff_sessioncookiestringOptionalThe session identifier. Omit it on the first call and store the value the response sets; every later call must send the same one or the engine treats the caller as a new visitor with no holds and no claims.

Request

The cookie jar carries the session between calls. Angle-bracketed values are the parameter types from the table above.

curl -s -b cookies.txt -c cookies.txt \
  "https://flowfinds.ai/api/offer"
const res = await fetch("https://flowfinds.ai/api/offer", {
  method: "GET",
  credentials: "include",
});
const data = await res.json();
import requests

s = requests.Session()
r = s.get("https://flowfinds.ai/api/offer")
data = r.json()

Recorded example

curl -s -b cookies.txt -c cookies.txt \
  "$FLOWFINDS_ORIGIN/api/offer"

Responses

200A live offer exists.

FieldTypeDescription
statusstring`offer`.
offerobject`our_price_usd`, `observed_low_usd`, `undercut_pct`, `undercut_basis`, `margin_pct`, `margin_basis`.
freshnessstringThe dated freshness line, computed at serve time.
refresh_failedbooleanTrue when the last attempt to refresh the observed listings failed — the dated observation survives, and says so.
comparisonobjectThe basis the undercut is measured against.
bundleobjectThe bundle deal derived from the offer, when one applies.
pre_shockobject`basis` (`observed` or `unverified`), `normal_price_usd` and a `note` stating what the undercut is measured against when the pre-shortage price was never established.
excluded_costsarrayCosts the margin figure does not include.
watchobjectThis session's watch state on the product, when the product is not servable to it.

200No offer can be served.

FieldTypeDescription
statusstring`refused`.
failed_legstring`research` when the product has not been through supplier research, `pricing` when the price failed the pre-shortage check.
reasonstring`not_yet_researched`, or the pricing refusal's own reason.
explanationstringThe sentence the screen shows.
excluded_costsarrayCosts the margin figure would not have included.

Errors

StatusReasonWhen
429The usage meter refused the call.

Related

Back to the API reference index, or read the cookbook for recipes that compose this endpoint with others.