frontmost

Frontmost AI API

Use this API to read how AI apps answer your buyers' questions about your business, and to change what Frontmost AI tracks. It gives a coding agent the same numbers as the Frontmost AI app and the MCP server.

Get a key

  1. Open https://app.frontmost.ai/team and go to API Keys.
  2. Name the key and choose what it can do. A Read Only key calls every GET route. A Read and Write key calls every route.
  3. Copy the key when it appears. Frontmost AI shows it once.

Every plan includes API keys. Every member of a workspace can create keys, see every key, and revoke any key. A revoked key stops working on the next request.

Authenticate

Send the key in the Authorization header of every request:

curl https://app.frontmost.ai/api/v1/workspace \
  -H "Authorization: Bearer $FRONTMOST_API_KEY"

Keep the key in an environment variable such as FRONTMOST_API_KEY. Do not put it in code that you commit.

First call

Call GET /workspace first. It returns the plan, its limits, and what is in use. Then call GET /projects to find project IDs.

curl https://app.frontmost.ai/api/v1/projects \
  -H "Authorization: Bearer $FRONTMOST_API_KEY"

Routes

Method and pathKeyWhat it does
GET /workspaceRead OnlyThe plan, its limits, and use. profiles.max_per_project is the most buyer profiles one project holds.
GET /projectsRead OnlyList projects. q filters by name or domain.
GET /projects/{id}Read OnlyOne project
GET /projects/{id}/scansRead OnlyDelivered scans, newest first. delivered_after takes a date.
GET /projects/{id}/metricsRead OnlyVisibility, Win Rate, Position, and Sentiment for one scope. group_by is app or scan.
GET /projects/{id}/rivalsRead OnlyRivals that the answers named, most named first
GET /projects/{id}/answersRead OnlyAnswers in scope, without their text. Filters: question_id, rival_id, named, cited_domain.
GET /answers/{id}Read OnlyOne answer with its text and citations
GET /projects/{id}/sourcesRead OnlySites that the answers cited, most cited first. Each site has a channel, such as editorial, reddit, or own_website. domain filters to one site, and channel filters to one channel.
GET /projects/{id}/questionsRead OnlyThe project's questions. active filters.
GET /projects/{id}/recommendationsRead OnlyRecommendations, open first. status is open, done, or dismissed.
GET /projects/{id}/profilesRead OnlyThe project's buyer profiles, with each name and who
POST /projectsRead and WriteCreate a project from a website, or continue a setup
PATCH /projects/{id}Read and WriteRename a project (name), or start or stop its scans (scanning)
POST /projects/{id}/questionsRead and WriteAdd 1 to 25 questions: {"questions": [{"text": "…", "topic": "…"}]}
PATCH /projects/{id}/questions/{question_id}Read and WriteReword (text), move (topic), pause, or resume (active) a question. A paused question keeps its history and does not count toward the plan's questions. No route deletes a question.
POST /projects/{id}/profilesRead and WriteAdd a buyer profile: name and an optional who
PATCH /profiles/{id}Read and WriteRename or describe a buyer profile
DELETE /profiles/{id}Read and WriteRemove a buyer profile. Its questions stay.
PATCH /recommendations/{id}Read and WriteSet status to done, dismissed, or open

The OpenAPI file has every parameter and response field.

Create a project

A new project starts from a website. Frontmost AI reads the site, then writes the first questions.

  1. Send POST /projects with domain and an Idempotency-Key header. Use a new random key, for example a UUID, for each new project.
  2. A ready project returns 201 with the project object.
  3. A setup that needs more time returns 202 with a project_setup object and a Retry-After: 30 header. Its next field holds the exact next call.
  4. Wait Retry-After seconds. Send POST /projects with {"setup_id": "…"} and no Idempotency-Key. Repeat steps 2 to 4.

A repeated call never makes a second project. A site that Frontmost AI cannot read returns 422 site_unreadable.

curl -X POST https://app.frontmost.ai/api/v1/projects \
  -H "Authorization: Bearer $FRONTMOST_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"domain": "example.com"}'

The same Idempotency-Key with the same body returns the first reply with Idempotent-Replayed: true. The same key with another body returns 409 idempotency_conflict. Frontmost AI keeps each key for 24 hours.

Scope

The metrics, rivals, answers, and sources routes take the same scope parameters:

ParameterValuesDefault
scan_ida delivered scan of the projectthe newest delivered scan
periodscan, week, monthscan
appone AI app of the projectevery app of the project
questionsall, branded, unbrandedall
compare_toprevious, noneprevious

Lists

A list returns {"object": "list", "data": [...], "has_more": true, "next_cursor": "…"}. limit is 1 to 100, and the default is 25. To get the next page, send the same request with cursor set to next_cursor. A cursor works only with the list and parameters that made it.

Errors

Every error has this shape. The message says what to do next. Quote request_id when you report a problem.

{
  "error": {
    "code": "invalid_param",
    "message": "period must be scan, week, or month.",
    "param": "period",
    "request_id": "req_…"
  }
}
StatusCodeWhat to do
401invalid_keyThe key is missing or unknown. Ask the person for a key from the Team page.
401key_revokedThe key was revoked. Ask the person for a new key.
403plan_no_apiThe workspace has no active plan. The person chooses a plan on the Billing page.
403needs_planThe plan is not running, so changes fail. Reads still work.
403key_read_onlyA Read Only key called a change route. Ask for a Read and Write key.
404not_foundNothing with this ID in this workspace, or no such route.
409idempotency_conflictThis Idempotency-Key was used with another body. Use a new key.
409request_in_progressA request with this Idempotency-Key is still running. Wait Retry-After seconds.
422invalid_paramA parameter is not valid. param names it.
422invalid_cursorThe cursor belongs to another list. Start the list again.
422question_limitThe change goes over the plan's questions. details has used, max, and adding. Pause a question to make room.
422project_limitThe plan's projects are all in use. details has used and max.
422profile_limitThe project has the most profiles it can hold. details has max. Remove a profile first.
422site_unreadableFrontmost AI could not read the website. Check the domain.
429rate_limitedToo many requests. Wait Retry-After seconds, then retry.
500internal_errorRetry with backoff. Quote request_id if it keeps failing.

A route that exists with another method returns 404, and the message names the methods it takes.

Rate limits

Each key has one budget for reads and one for changes. A browser sign-in has the same two budgets for each person. A month scope costs more than a scan or a week. Read the headers on every response. Do not hard-code the numbers, because they can change.

HTTP/2 429
Retry-After: 3
RateLimit-Limit: 60
RateLimit-Remaining: 0
RateLimit-Reset: 3

On a 429, wait Retry-After seconds plus a short random delay, then send the request again.

Compatibility

Command line

The Frontmost AI CLI calls this API from a terminal. Each route on this page is a command.

brew install frontmost-ai/tap/frontmost
frontmost login
frontmost metrics --period week

Without Homebrew, run npm install -g github:frontmost-ai/cli. It needs Node.js 22.12 or later. Add --json to any command to get the API response, unchanged. Source: https://github.com/frontmost-ai/cli

Use with a coding agent

Give the agent the key and this page:

export FRONTMOST_API_KEY=fmk_…
# Docs: https://app.frontmost.ai/docs/api.md

To connect an AI app such as Claude or ChatGPT instead, use the MCP server: https://frontmost.ai/connect

Pick what you’re comfortable with. You can change it anytime.

Strictly NecessaryKeeps you signed in and remembers your choice.
Always Active