Docs · Authentication

DocsBoth tracks

Authentication

API tokens and signing in from the command line.

View as MarkdownThis page as plain text
llms.txtIndex of every docs page, for agents

API tokens

The API and the starter's frontieror command sign in with a personal API token.

  • Create one on the dashboard under Settings → Security → Generate token. It is shown once, so copy it then.
  • A token starts with fo_. It acts as you, on your team.
  • You have one token at a time. Generating a new one, or signing in with frontieror init, replaces it, and the old one stops working at once.
  • Tokens don't expire. Keep yours out of code you share, and replace it if it leaks.

Using a token

Send it in the Authorization header of every request:

import os

import httpx

api = httpx.Client(
    base_url="https://frontieror-challenge.com/api/v1",
    headers={"Authorization": f"Bearer {os.environ['FRONTIEROR_TOKEN']}"},
)
print(api.get("/me").json())

A missing, wrong or replaced token gets 401 with “Missing or invalid API token.”

Signing in from the starter

uv run frontieror init opens your browser at /device with a code. Check that it matches the code in your terminal, then Approve. The command receives a new token and saves it as FRONTIEROR_TOKEN in .env. The code is valid for 10 minutes.

To use an existing token instead, run uv run frontieror init --token fo_…, or set FRONTIEROR_TOKEN in the environment or in .env.

Never approve a code that someone else sent you: approving gives them a token for your account.

Signing in from your own tool

The same browser sign-in works for any command-line tool, following the OAuth device flow (RFC 8628). Only the client id frontieror-cli is accepted.

  1. POST /api/v1/device/code with client_id=frontieror-cli, form-encoded or as JSON. The response has device_code, user_code, verification_uri, verification_uri_complete, expires_in (600 seconds) and interval (5 seconds).
  2. Open verification_uri_complete for the user, who approves the code while signed in.
  3. Every interval seconds, POST /api/v1/device/token with grant_type=urn:ietf:params:oauth:grant-type:device_code, the device_code and the client_id.

Until the user decides, the token request returns 400 with {"error": "authorization_pending"}. It ends with one of:

ResponseMeaning
200 {"access_token": "fo_…", "token_type": "Bearer"}Approved. The token is handed out once and replaces the user's previous token.
400 access_deniedThe user denied the sign-in.
400 expired_tokenThe code expired before it was approved.
400 invalid_grantThe device code is unknown or was already used.