Google Analytics, Vercel Web Analytics, Leadsy and the TikTok Pixel stay off until you accept. The help chat starts once you have chosen. The scheduling button starts once you have chosen. Read our Privacy Policy.

Skip to content
StellarFirmStellarFirm
Mission manual
Esc

Type a word to search every page. Try , or .

Module 09 · API

StellarFirm API endpoints

Every public StellarFirm API route with its method, what it needs, and what it answers. The same list is in the OpenAPI 3.1 file at /openapi.json.

View as Markdown
On this page

The routes below are the whole public StellarFirm API. Each one is also in the OpenAPI file, with its parameters and answer schemas. A route answers 405 with an Allow header for any method not listed here.

At a glance#

Method and pathSign-inWhat it does
GET /api/healthNoneSays the web app is up.
GET /api/site-bannerNoneReads the notice at the top of the site.
GET /api/entitlementSessionSays whether the account may run.
GET /api/credits/balanceSessionReads the account's credits.
POST /api/email/unsubscribeSigned tokenStops the later onboarding emails.
GET /api/try/statusNoneReads the free trial's status for the visitor.
POST /api/try/promptNoneSends one free prompt and streams the assistant's work.

GET /api/health#

Answers 200 with ok: true while the web app is running. Use it for an uptime check.

json
{ "ok": true, "service": "...", "surface": "ui", "agent": "not-hosted-here" }

GET /api/site-banner#

The notice shown at the top of the site, or null when there is none. It is the same for everyone and may be cached for half a minute.

FieldTypeMeaning
bannerobject or nullThe notice, or null.
banner.kindpromo or warningA promo shows on the public site only. A warning shows everywhere.
banner.messagestringThe notice text.

GET /api/entitlement#

Says whether the signed-in account may run: an active trial, a licence, or free Hobby after the trial. Only a 200 with ok: true means the account may run. It is never cached.

Statusstatus fieldMeaning
200licensed, trial or hobbyThe account may run. Ask again within recheckAfterSeconds.
401signed-outNo signed-in session.
403invalidThe account may not run.
503unconfigured or unavailableThe account could not be checked. Try again shortly.

A 200 answer for an account that has the premium models also carries premiumModels: true and codingSubscription: true. The premium models are open to an account on its trial, with a licence, in a university, or on a paid plan. An account on the free plan after its trial gets neither field, and a client reads a missing field as no. The free plan keeps running on the open models.

A 200 answer also carries assistantLimit, how many named assistants the account's plan lets it hire, and teamLimit, how many teams of assistants it lets it have. A missing teamLimit means the plan puts no limit on teams, so a client must never read it as zero. Neither limit removes anything: an account that already has more keeps all of it and can still rename, move and delete, and only a new assistant or team is held back.

Every answer except 200 also carries the standard error object. See Errors.

GET /api/credits/balance#

The account's balance as a number of StellarFirm credits, never money. Answers { "credits": 120 } for example. It answers 503 with the code balance_unavailable when the balance cannot be read.

POST /api/email/unsubscribe#

One-click unsubscribe from the later onboarding emails. Send the token from the link in the email as the query parameter. It answers 200 with a plain text line, 400 with invalid_token for a token that is not valid, and 502 with upstream_failed when the later emails are still scheduled and you should try again.

GET /api/try/status#

The free trial on the landing page gives a visitor with no account a few free prompts with three assistants: the Coder, Marketing and the Product owner. This route says whether the trial is open and how many prompts the visitor has left. The visitor is told apart by network address, with no sign-in and no cookie. It counts nothing and is never cached. It answers 404 with the code not_found while the trial is switched off.

json
{ "open": true, "promptsLeft": 3, "promptsPerVisitor": 3 }
FieldTypeMeaning
openbooleanFalse once this month's allowance for the trial is used up.
promptsLeftintegerFree prompts this visitor has left.
promptsPerVisitorintegerFree prompts each visitor gets.
reopensOndateThe day the trial opens again (UTC, the first day of the next month). Present only while it is closed.

POST /api/try/prompt#

Sends one free prompt. The body is JSON, and the request must come from a person in a browser on the site: a script is refused with try_refused.

json
{ "assistant": "coder", "content": "Make a one page site for a bakery." }
FieldTypeMeaning
assistantcoder, marketing or product-ownerWhich assistant gets the prompt.
contentstringThe prompt, 1 to 2000 characters once trimmed.

A visitor may run one prompt at a time. The assistants work on their own computers, so a prompt can take several minutes, and it stops after about twelve. A step that would need an Approve never runs: the answer stops there and says so.

Send Accept: text/event-stream to read the work as it happens. Each event is one JSON object on a data: line, and a comment line now and then keeps the connection open.

Event typeFieldsMeaning
startedassistant, promptsLeftThe prompt was accepted and counted.
activitytextA short line saying what the assistant is doing.
textdeltaMore of the answer's words.
artifactartifactA file the assistant published: id, kind, title, and content for a kind the page draws (html, svg, markdown, csv, json) when it is small enough. Other kinds are listed with no content.
doneanswer, promptsLeft, heldThe whole answer as Markdown. held is true when it stopped at a step that needs an Approve.
errorcode, promptsLeftThe prompt could not be answered. The code is try_failed; promptsLeft says how many are left.

Without that header, the final done event comes back as JSON, with the artifacts in one list.

A prompt that is refused before it starts answers the shared error shape with a status and code: 429 try_used_up when the visitor used every free prompt, 429 try_busy while a prompt is running or too many run at once, 503 try_ended when this month's trial is used up (with reopensOn), 403 try_refused when the check that a person sent it fails, and 404 not_found while the trial is switched off.

Unknown routes#

Any other address under /api answers 404 with the error code not_found, in JSON, never an HTML page.