Documentation

POST /api/product

Publish a product of the founder's own into the store engine.

RequestPOST /api/product
AuthenticationSession cookie required
Handlerbackend/server.py

What it does

Accepts a product the founder supplies rather than one the catalog found: name, description, price and images. Images are size-checked, and an oversized payload is refused with 413 rather than truncated. On success the store engine has a manifest and the response names its storefront and browsable path.

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.
namebodystringRequiredThe product name. Refused as `invalid_name` when unusable.
descriptionbodystringRequiredWhat the product is. Refused as `invalid_description` when unusable.
price_usdbodynumberRequiredThe asking price. Refused as `invalid_price` when unusable.
imagesbodystring[]RequiredProduct images. Refused as `invalid_images`, or `images_too_large` with 413. A product with no real photo is not servable — the reveal is the product.
product_idbodystringOptionalPublish under an existing identifier rather than minting one.

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 \
  -X POST -H 'Content-Type: application/json' \
  -d '{"name":"<string>","description":"<string>","price_usd":"<number>","images":"<string[]>","product_id":"<string>"}' \
  "https://flowfinds.ai/api/product"
const res = await fetch("https://flowfinds.ai/api/product", {
  method: "POST",
  credentials: "include",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "<string>",
    "description": "<string>",
    "price_usd": "<number>",
    "images": "<string[]>",
    "product_id": "<string>"
  }),
});
const data = await res.json();
import requests

s = requests.Session()
r = s.post("https://flowfinds.ai/api/product", json={
    "name": "<string>",
    "description": "<string>",
    "price_usd": "<number>",
    "images": "<string[]>",
    "product_id": "<string>"
  })
data = r.json()

Recorded example

curl -s -b cookies.txt -c cookies.txt \
  -X POST -H 'Content-Type: application/json' \
  -d '{"name":"…","description":"…","price_usd":39,"images":["data:image/…"]}' \
  "$FLOWFINDS_ORIGIN/api/product"

Responses

200The product was published.

FieldTypeDescription
statusstring`published`.
product_idstringThe identifier the product was published under.
storefrontstringThe storefront path from the manifest.
browsable_pathstringThe path that must resolve for the store to count as ready.

Errors

StatusReasonWhen
400A field failed validation. The body names the failing field.
401The session has no account.
409The identifier is already in use, or a build is already running for it.
413images_too_largeThe image payload exceeds the accepted size.
500generation_failedThe store engine raised while building.

Related

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