Portfolio

Api Portfolio Post Import Fetch

Phase 1: validate + estimate credit cost for a post-import AI fetch.

Accepts a freshly-imported ticker list + action type ('news' or 'research') and returns the gate decision: how many credits the Phase 2 fetch will cost (low + high bounds), or a 402/422 with branch-specific context if the request can't proceed.

Plus-tier gated (require_min_tier("plus")). plus_trial users are accepted by the tier check but rejected at the AI-action gate per OWNER Q3 ratification (research-deck + news AI summaries are upgrade-only; non-AI actions remain trial-accessible — none implemented in Phase 1).

Request body: {action: "news"|"research", tickers: [str, ...], idempotency_key: str}

Response: PostImportFetchEstimateResponse. Always 200 on the OK branch; 402 on tier/balance/cap rejection; 422 on overflow; 400 on malformed input.

Does NOT call the AI provider, NOT decrement credits, NOT stream. Phase 2 wires those in.

post/api/portfolio/post-import-fetch

Request

  • Base URL: https://www.oxfordledge.com (the document declares no server; this is the origin it was published from)
  • URL: https://www.oxfordledge.com/api/portfolio/post-import-fetch
  • Auth: none declared

Response

Successful Response

estimated_credits_lowinteger required

Lower-bound credit charge (1 credit per validated ticker on success). FE renders this as 'will cost N credits'.

estimated_credits_highinteger required

Upper-bound credit charge — low + 50% retry headroom (per OWNER Q5 ratification 2026-05-28). FE renders this as 'up to N if retries needed'.

tickers_validatedstring[] required

Server-validated, deduped, and capped ticker list. May be empty on rejection branches.

idempotency_keystring required

Echo of the client-supplied UUID, threaded through to Phase 2 for collapse-on-retry.

trial_lockedboolean nullable

True on the plus_trial + AI-action branch (402). Per OWNER Q3 ratification 2026-05-28: trials may not consume AI features.

insufficientboolean nullable

True when credit_balance < estimated_credits_low (402). Inline upsell branch.

monthly_cap_exceededboolean nullable

True when MTD post-import spend + low > 80% of TIER_BUNDLED_CREDITS (402). Per OWNER Q8 ratification 2026-05-28.

too_many_tickersboolean nullable

True when deduped ticker count > POST_IMPORT_MAX_TICKERS_PER_CALL (422). Per OWNER Q1 ratification 2026-05-28: global 25-ticker cap.

balanceinteger nullable

Current credit balance — surfaced on the insufficient + OK branches.

neededinteger nullable

Credits needed to clear the lower bound — surfaced on the insufficient branch.

monthly_capinteger nullable

The 80% hard cap on MTD post-import AI spend — surfaced on the monthly_cap_exceeded branch.

monthly_spend_to_dateinteger nullable

MTD post-import-AI credit spend — surfaced on the monthly_cap_exceeded branch.

max_tickers_per_callinteger nullable

The per-call ticker cap — surfaced on the too_many_tickers branch (gives FE the exact value for the error copy).

submitted_countinteger nullable

Number of unique tickers the client submitted — surfaced on the too_many_tickers branch.

upgrade_urlstring nullable

Plan upsell URL — surfaced on the trial_locked / insufficient / monthly_cap_exceeded branches.

messagestring nullable

Human-readable copy for the active branch. Placeholder pending VOICE+DESIGN co-pass before user-visible launch.

decisionstring nullable

Machine-readable decision code ('ok', 'trial_locked', 'insufficient_credits', 'monthly_cap_exceeded', 'too_many_tickers', 'bad_request'). Mirrors HTTP status.

actionstring nullable

Echoed action type ('news' or 'research') on the OK branch.

modelstring nullable

AI model identifier the Phase 2 fetch will use — surfaced on the OK branch so the FE can show a 'powered by' chip if desired.

max_tokensinteger nullable

Per-ticker output-token cap the Phase 2 fetch will apply — surfaced on the OK branch.

Changes

No recorded changes to this operation across all 1 revision of this API.