Documentation

GET /api/find

Serve this session's product, minting a hold if it does not have one.

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

What it does

The single-product entry point. `hold_for()` resolves the session's existing hold or mints one, and the find meter lives inside that function rather than in the handler — every caller that can create a hold is metered by the same code. The served product is recorded in `seen`, and the `find_served` and `shown_field` milestones advance. A hold lasts 30 minutes; `held_minutes` in the response states that rather than leaving the client to assume it.

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/find"
const res = await fetch("https://flowfinds.ai/api/find", {
  method: "GET",
  credentials: "include",
});
const data = await res.json();
import requests

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

Recorded example

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

Responses

200A product is held or could be minted for this session.

FieldTypeDescription
idstringCatalog identifier for the product.
namestringProduct name from the catalog.
scorenumberComputed by `server.score` from the evidence legs, today's date and evidence staleness. Never stored, never hand-written.
evidence_age_daysnumberAge of the oldest supporting evidence leg, in days.
freshnessnumberDecay factor derived from evidence age, rounded to three decimals.
held_minutesnumberLength of the hold window in minutes — 30 at the time of writing, served rather than assumed.
servablenumberHow many catalog products remain servable to anyone right now.
yoursbooleanTrue on the product resolved for this session.
sampleobjectSample-order quote from `sample_market.quote`, or its refusal.
preview_availablebooleanWhether `/preview/<id>` will resolve. False when no live offer exists, because a preview with an invented price is worse than no preview.
preview_urlstring | null`/preview/<id>` when a preview exists, otherwise null. Served so no client hand-builds the path.
evidencearrayThe catalog evidence rows behind the find: claim, source, URL and date per leg.

200Nothing can be served: the catalog is exhausted, everything is held by other founders, this session has passed on everything, or the session is at its own claim allowance.

FieldTypeDescription
statusstring`refused`.
reasonstringOne of `all_held`, `passed_out`, `catalog_exhausted` or `claim_limit_reached`. These are deliberately distinct: being at your own allowance has a different exit from the catalog being taken.
explanationstringThe sentence the screen shows.
servablenumberProducts still servable to somebody.

Example response

{
  "id": "…",
  "name": "…",
  "score": 78,
  "evidence_age_days": 6,
  "freshness": 0.918,
  "held_minutes": 30,
  "servable": 11,
  "yours": true,
  "preview_available": true,
  "preview_url": "/preview/…"
}

Errors

StatusReasonWhen
429usage refusalThe find meter inside `hold_for` refuses: this session has spent its allowance for the period. The body is `_usage.refusal(...)` and names the tier and the limit.

Related

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