# Prompt Exchange v0

Authenticated API on this app's HTTPS origin. Sign in with AuthReturn app `prompt-exchange`; send the app-scoped bearer JWT. Exchange a FairyStack session capability at `POST /api/apps/prompt-exchange/agent-token` on the control origin for agent access. Keep credentials private.

- `GET /api/workspace`: models, owned/shared markets, learned trader scores, credit balances, and settlement receipts. Returned answers are blinded until the owner selects a winner; other participants never receive private answer text.
- `POST /api/recommend`: `{prompt, weights:{cost:0.35,speed:0.25}}`. Weights range 0–1. Returns model utility ranking and normalized preference probabilities. Task categories are a simple keyword classifier; initial forecasts are catalog priors. No benchmark-proof guarantee.
- `POST /api/markets`: `{prompt, mode:"compare"|"route", shared:false, weights:{cost:0.35,speed:0.25}, clientId:"unique-12-to-80-character-id"}`. Returns 202 and a persisted market. The same identity retries the same request; a conflicting payload returns 409. Compare mode opens a 10-second prediction window before concurrent inference; route mode runs only the highest-utility model. Prompts are capped at 12,000 characters, one active run per user, 20 runs/hour. Paid inference uses BrightWrapper; no subscription integration.
- `POST /api/markets/<id>/bet`: `{model,stake}`. Other participants may stake 1–100 play credits only on an explicitly shared prompt before its window closes. Owners cannot bet on their own verdicts. Credits have no monetary value.
- `POST /api/markets/<id>/winner`: `{winner:"candidate-id"|"none"}`. Owner-only; ready comparisons only. Atomically settles once, reveals model identity/time/log charge, updates task-specific preference routing, and appends a SHA-256 receipt. A 2% fee on winning profit goes to the simulated platform ledger; no winning ticket or all-rejected verdict refunds all stakes.
- `POST /api/markets/<id>/cancel`: owner-only. Refunds unsettled stakes and abandons any submitted provider tasks. BrightWrapper has no cancellation endpoint; abandonment does not imply the provider stops or refunds inference.

Execution states: queued → running/disconnected → ready (execution finished, awaits preference) → completed/cancelled; failed/timed_out are terminal and refund stakes. Each market has a persisted 180-second deadline; each provider request has a 10–15-second timeout. On restart saved provider task IDs resume observation. Interrupted submissions without saved IDs fail rather than repeating a potentially charged request. Unknown model fallback rejects that candidate.

Settlement options live in the app's **Settlement options** view. The centralized credit ledger is implemented. Contract escrow is a design comparison only: signed off-chain forecasts, collateral escrow, attested verdicts, batched payout minus rake. No blockchain, wallet, collateral token, or cash gambling is active. Both architectures need an honest outcome oracle; preventing same-account betting does not prevent collusion or multiple-account manipulation.

Completed provider results supply the recorded charge as cost_usd. Older task logs report cost rounded to $0.0001. Missing cost is null, never silently zero. Timing is provider-measured generation duration. The default prompt asks for concise answers, but it is not a strict provider token cap. Inference spending and play-credit rake are separate.

## Optional FairyStack routing connector (v0.2)

The connector lives in Prompt Exchange. It uses FairyStack's existing `/api/app-sessions` boundary; no FairyStack source code, native harness, provider endpoint, or tool loop is replaced. It routes once at session creation, then the native runtime keeps the conversation. Normal FairyStack composer traffic is unchanged.

A client that already starts app-owned FairyStack sessions can change only its base URL to this app's origin and retain its own `X-API-Key`, payload, status reader, and Stop request. The key is forwarded only to `https://jessald.fairystack.com`, never persisted, and FairyStack still owns authentication, consumer/owner isolation, session limits, quotas, budget estimates, tools, and cancellation. Existing upstream HTTP error status, content type and body pass through. Upstream redirects are rejected.

- `POST /api/app-sessions`: FairyStack's `{objective,client_mutation_id,client?,model?,effort?,memory?}`. Omit `model` or use `auto` / `prompt-exchange/auto` for routing. An explicit model passes through unchanged. An explicit runtime constrains auto routing to that runtime. `routing` is the connector's only additional field; it is removed before forwarding.
- `routing: {mode:"auto"|"shadow"|"bypass",weights:{cost:0.35,speed:0.25}}`: auto selects an enrolled model and effort; shadow records its recommendation and lets FairyStack use the caller's original fields/native defaults; bypass forwards the original fields. Default auto. Shadow/bypass do not run an extra model. Bypass with a pseudo-model `auto` is rejected; omit it instead.
- `GET /api/app-sessions/<id>` and `POST /api/app-sessions/<id>/stop`: the existing native contract, using the caller's same integration key. Responses remain FairyStack's JSON shape. Creation adds `X-Prompt-Exchange-Decision`, `X-Prompt-Exchange-Routing`, and `X-Prompt-Exchange-Model` response headers.
- Authenticated owner UI uses the same routes with its Prompt Exchange bearer; a narrowly scoped, owner-bound `sessions:create` key is provisioned server-side. Other app accounts cannot use that key. Existing clients can use their own native integration keys without this UI enrollment.

The enrolled pool was read from FairyStack's live runtime catalog: GPT-6.1-Sol, Claude Opus 5.5, GPT-6-Luna. The server's encrypted enrollment contains the pool and price snapshot. FairyStack validates each selected model against its current catalog; a removed/unavailable model fails visibly. Refreshing the enrollment is required to add newly offered models or update price/speed priors. Capability and speed utilities are hand-set experimental priors; matching blind-answer preferences are weak text evidence, not proven native-agent performance. There is no guarantee of best-model selection or resistance to benchmark gaming.

Claude's native runtime reported subscription billing at enrollment. Codex uses its existing native account. API-equivalent `cost_usd` is usage accounting, not proof of a cash charge or unused subscription quota. This connector does not scrape provider cookies, borrow subscriptions from other users, or increase any budget/policy.

Delivery has a 15-second upstream timeout, persisted submission identity/selection, and a visible failed/timed-out outcome. A restarted or uncertain submission is recovered only by explicitly retrying the same `client_mutation_id`; the same routing decision is reused and FairyStack deduplicates the native session. A conflicting payload is 409. Native execution and its deadline stay owned by FairyStack. Owner-UI observation resumes saved session IDs after restart; disconnected reads have a bounded observation deadline and retain an ordinary native-session link when observation times out. Stop never implies a refund.

Example: use your existing FairyStack integration key with a 20-second HTTP timeout; never put it in frontend code or source control.

```json
{
  "objective": "Investigate the requested issue in the existing app.",
  "client_mutation_id": "caller-generated-stable-request-id",
  "model": "auto",
  "routing": {"weights": {"cost": 0.35, "speed": 0.25}}
}
```

Open `/#connector` for native routing receipts. The prompt workspace's **Run on FairyStack** action routes through this boundary and links the native conversation. Switching a client's base URL back to FairyStack removes the layer; no migration or FairyStack code rollback is needed.
