# Oxaide for agents: brief schema and status checks

This document is the machine-readable brief schema for agents. It does not
create a new API, and it does not change pricing, payment, or credit rules.

## How agents submit: use the existing human brief flow only

Agents submit exactly the way a human does, through the existing human
brief form flow:

- On the site: the brief form on https://oxaide.com/ (the same form a
  human uses), or
- By email: brief@oxaide.com, or
- Via the form's existing endpoint: `POST /api/audit/inquiry` with
  `brief` and `email` (the endpoint the site's own brief form posts to).

Do NOT invent a new unauthenticated money API. There is no new route in
this document that burns a pack credit or charges a card. Payment happens
only on the quoted job's own Pay step: Stripe checkout, or an explicit
pack-credit confirmation (a button POST, never a GET link, never a
prefetch). A credit is never burned by visiting, linking to, or polling
a status page.

## Brief schema

Submit one brief per job. Keep the brief to 2–8 lines.

| Field | Required | Notes |
| --- | --- | --- |
| `brief_text` | Yes | 2–8 lines: who the buyer is, what is being shipped or granted on terms, and what decision the verdict must support. Plain text, no internal jargon. |
| `buyer_uen` | If known | The buyer's Singapore UEN, if known. Omit it (do not guess) when unknown. |
| `terms_requested` | If known | The terms being considered, for example 30 or 60 days, or a cap amount. Omit when unknown. |
| `contact_email` | Yes | The email the quote and the pack go to. This is the buyer contact, not an agent service address unless the buyer has authorised it. |

Example payload shape for the existing form endpoint (field names are
the form's own `brief` and `email`; the other fields belong inside the
brief text when they are known):

```json
{
  "brief": "Buyer: <name> (<buyer_uen> if known).\nTerms requested: <terms_requested>.\n<2-8 lines describing what is being shipped and what the verdict must decide.>",
  "email": "<contact_email>"
}
```

## Expected response

A successful submission returns a quote reference (a job id) and a
status page for that job:

- Quote reference: the job id returned by the form endpoint.
- Status page: `https://oxaide.com/brief/<job-id>` (the same job is also
  trackable at `https://oxaide.com/audit/<job-id>` for form-lane jobs).
- The quoted job page shows the fixed quote, a GST breakdown, and a
  promo field BEFORE any Pay click. Nothing is charged or burned by
  opening that page.

Do not treat a quote reference as payment. The job starts only after
the Pay step on that status page.

## Status checks: how to poll a quoted job

Poll the job's status page data, not the rendered UI. Do not scrape
the UI.

- For brief-lane jobs: `GET /api/brief/status?id=<job-id>` returns
  JSON with `ok`, `id`, `status`, `quote_sgd`, `created_at`,
  `quoted_at`, `paid_at`, `delivered_at`, and `expires_at`.
- For form-lane (audit) jobs: `GET /api/audit/status?id=<job-id>`
  returns the same safe subset (plus `quote_price` and `quote_tier`).
  Both endpoints return the safe subset by unguessable job id, with no
  token; they never return the full delivery pack to an unauthenticated
  poller beyond what the status page itself shows.

Job states you will see:

- `quoted` — fixed price issued, not yet paid. Polling a quoted page
  changes nothing; the job only moves when someone pays or re-quotes.
- `paid` — paid, queued or building (the audit lane may show this as
  `draft` while building; the brief tracker maps it to running).
- `queued` / `running` — building. The brief tracker uses `paid` /
  `running` for this phase; treat either as "in progress".
- `delivered` — pack delivered to the contact email and available on
  the status page. Stop polling.
- `cancelled` — quote cancelled. Nothing was charged for an unpaid
  quote; a bundle-paid job cancelled before it started has its pack
  credit restored once. Stop polling.
- `failed` — could not be completed. A human reviews failures for
  refund or a free re-run; do not re-pay without a human reply.
- `needs_human` — custom scope, fixed quote by a human within
  1 business day. Nothing to pay until that quote is approved.

## Poll interval guidance

Do not hammer the status endpoint.

- For a human job, poll no faster than once every 5 minutes.
- The status pages themselves refresh on their own while a job is in
  progress: the brief page polls every 15 seconds while building (3
  seconds only immediately after a Stripe redirect, and it stops after
  45 minutes with an explicit message), and it does not poll a quoted
  job at all (a quoted job only changes via pay or re-quote, both of
  which navigate). Those UI intervals are the site's own refresh
  behaviour, not a polling allowance for API callers: API callers use
  the 5-minute guidance above.
- Stop polling at `delivered`, `cancelled`, or `failed`.

## Pricing reminder (see /pricing and /llms.txt)

Pack S$390; 3-pack S$990 (90 days; optional monthly refill S$890/mo, packs only, cancel anytime); Firms retainer S$3,000/mo
(10 screens, 2-hour SLA, 4 roll over); Terms Cover S$2,490/yr;
UEN watch S$490/yr, Supplier watch S$990/yr, Award Intel S$990/yr (from S$490/yr). Board-size and custom scopes quoted fixed by email. Prices in Singapore dollars; no GST is added to
the S$390 Pack (Pack S$390 / GST S$0 / Total S$390). Verdicts are
ship, COD-only, cap-terms, or walk. Every line is cited; refund if a
key claim is unbacked. No client numbers, logos, or testimonials are
promised here.
