# SUIT Web API > Read-only API for SUIT, the internal investment system of Banner Ridge Partners (private equity). > Every endpoint returns the data behind a page of the SUIT web app, with the same filters and sorting. > If you are an AI agent asked to get SUIT data: use this API. Do not open the SUIT web app in a browser. This guide is served without a key at `/`, `/llms.txt` and `/api/v1/guide`. The full machine-readable description (OpenAPI / Swagger 2.0 JSON, every parameter and response field documented) is at `/swagger/docs/v1`. People can try calls at `/swagger`. ## Base URL Use the scheme and host you fetched this guide from, e.g. `https:///api/v1/funds`. ## Authentication - Send the API key on every request in the `X-Api-Key` header: `X-Api-Key: suit_...` - Never put the key in the URL, and do not repeat it back, log it or save it in files. In a shell, keep it in an environment variable. - Personal keys are created in SUIT under your name > API Keys (/account/api-keys). A personal key acts as its user: it works only while the user is Active, has a confirmed email and has Worker access or above, and the user's Privacy Mode applies (anonymised names in the Reporting Data exposure tables). - System keys are created by an administrator (/admin/api-keys). They are not tied to a user and can read everything in this API. - Check a key with `GET /api/v1/me` (returns the key's name, whether it is a system key, its expiry and, for a personal key, its user). - Every call is recorded in SUIT's activity log under the key. You need an HTTP client that can send a custom header (curl, Python requests, PowerShell Invoke-RestMethod, etc.). Tools that fetch a URL but cannot set headers will get 401. curl -s -H "X-Api-Key: $SUIT_API_KEY" "https:///api/v1/me" ## Conventions - All endpoints are `GET` and return JSON (UTF-8). Property names are PascalCase, e.g. `FundName`. - Lists return `{ "Count", "SortColumn", "SortDirection", "PageNumber", "PageSize", "Items": [...] }`. - Totals are never rows: where a page shows a total row, the response has a separate `Total` next to the rows (Portfolio Reporting Data tables and the completed deal endpoint), so summing rows does not double count. Only `/api/v1/funds` pages (default 1000 per page, max 5000; request the next `pageNumber` while `Count` equals `PageSize`). Every other list returns all matching rows. - Single items (`/{id}`) return the object itself, or 404 when it does not exist or was deleted. - Query parameters are case-insensitive. Id lists are comma separated: `ids=1,2,3`. Text filters (`name`, `search`, `seller`) match "contains", case-insensitive. - Sorting: `sortColumn` and `sortDirection` (`asc` or `desc`). Each endpoint lists its sort columns; unknown values return 400 with the allowed list. - Date parameters are `yyyy-MM-dd` and mean that calendar date in US Eastern time. - Dates in responses are ISO 8601 in UTC with a `Z`: - Timestamps (`CreatedTimestamp`, `UpdateTimestamp`, `ExpiresTimestamp`) are real moments in time. - Calendar dates (record date, statement date, bid dates, payment date, ...) are stored as midnight US Eastern, so `2026-03-31T04:00:00Z` means 31 March 2026. Convert to US Eastern (or take the UTC date part) to get the calendar date. - Amounts are full, unformatted numbers (not thousands or millions). Fund, interest and statement amounts are in the fund's currency (see `CurrencyCode` on the fund). The web app shows some filters in millions; the API always takes full amounts. - Ratios are fractions: 0.25 means 25% (ownership, NAV share, IRR, price as a share of NAV, cost share). Exception: fund fee rates (`ManagementFeeCommitment`, `ManagementFeePostCommitment`, `IncentiveFee`) are in percent (1.5 means 1.5%). - MOIC and DPI are multiples (1.5 means 1.5x). - Enums are numbers. Most rows carry the label next to the number (e.g. `DealType` and `DealTypeName`); the lookup endpoints list every value, and `/swagger/docs/v1` lists the values of each enum field. - Errors return `{ "Message": "...", "Detail": null }` with: - 400: a parameter is invalid (the message names it and the allowed values). Fix the request; do not retry unchanged. - 401: missing, invalid, revoked or expired key. 403: the key's user is not allowed (inactive, unconfirmed email or below Worker). - 404: not found. 500: server error (logged in SUIT; retrying once is fine). ## SUIT terms - Banner Ridge fund / entity: Banner Ridge's own funds and legal entities (`/api/v1/entities`). The Banner Ridge funds are the entities with `FundEntity = true`; the Reporting Data "Banner Ridge Fund" filter (`entityIds`) takes their entity ids. - Fund: an underlying private equity fund that Banner Ridge buys interests in (`/api/v1/funds`). Fund manager = GP (`/api/v1/fund-managers`). - Pipeline deal: an opportunity Banner Ridge is reviewing or reviewed (`/api/v1/deals`). Its deal interests are the fund positions offered (fund, commitment, unfunded, NAV) (`/api/v1/deal-interests`). - Completed deal: a pipeline deal Banner Ridge won and has closed or is closing (Closed, Pending Close or Pending Signing) (`/api/v1/completed-deals`). Its completed deal interests are the fund interests bought (`/api/v1/completed-deal-interests`), each split between buying entities (Banner Ridge entities) with their costs, capital account statements and capital activity. - A completed deal has an internal name (`Name`) and the broker's name (`OriginalDealName`); searches match either. ## Endpoints and the web app page each one mirrors | Endpoint | Returns | Web app page | |---|---|---| | `GET /api/v1/reports/reporting` | Portfolio Reporting Data: every table on the page | `/reports/reporting` (Reports > Reporting Data) | | `GET /api/v1/funds` | Funds list (paged) | `/funds` (Funds > Funds); `/funds/manager/{fundManagerId}` = the `fundManagerId` filter | | `GET /api/v1/funds/{fundId}` | One fund | `/funds/{fundId}` (the fund's own fields) | | `GET /api/v1/funds/in-completed-deals` | Funds offered in the Reporting Data "Fund" filter | Fund dropdown on `/reports/reporting` | | `GET /api/v1/fund-managers` | Fund managers (GPs) | `/funds/manager-list` (Funds > Managers); `/funds/manager-list/{coverageUserId}` = the `coverageUserId` filter | | `GET /api/v1/fund-managers/{fundManagerId}` | One fund manager (its list row) | `/funds/managers/{fundManagerId}` | | `GET /api/v1/fund-managers/in-completed-deals` | Managers offered in the Reporting Data "Fund Manager" filter | Fund Manager dropdown on `/reports/reporting` | | `GET /api/v1/entities` | Banner Ridge entities with owners, subsidiaries and deal allocations | `/accounting/entities` (Accounting > Entities) | | `GET /api/v1/entities/{entityId}` | One entity | `/accounting/entities#{entityId}` | | `GET /api/v1/deals` | Pipeline deals | `/deals` (Deals > Deals) | | `GET /api/v1/deals/{dealId}` | One pipeline deal (its list row) | `/deals/{dealId}` | | `GET /api/v1/deals/{dealId}/interests` | Interests offered in one deal | Interests table on `/deals/{dealId}` | | `GET /api/v1/deal-interests` | Pipeline deal interests, filtered by deal, fund or text | Interests table on `/deals/{dealId}` | | `GET /api/v1/deal-interests/{dealInterestId}` | One pipeline deal interest | Its row on `/deals/{dealId}` | | `GET /api/v1/completed-deals` | Completed deals | Completed Deal dropdown on `/accounting/completed-deals` and `/reports/reporting` | | `GET /api/v1/completed-deals/{completedDealId}` | Everything on a completed deal's page | `/accounting/completed-deals#{completedDealId}` (Accounting > Completed & PSA Deals) | | `GET /api/v1/completed-deal-interests` | Completed deal interests across all deals, filtered by deal, fund or text | Interests table on `/accounting/completed-deals` | | `GET /api/v1/completed-deal-interests/{completedDealInterestId}` | One completed deal interest | Its row on `/accounting/completed-deals#{completedDealId}` | | `GET /api/v1/me` | The API key and its user | none (keys: `/account/api-keys`, `/admin/api-keys`) | | `GET /api/v1/deal-types`, `/api/v1/sub-deal-types`, `/api/v1/deal-strategies`, `/api/v1/deal-stages` | Deal dropdown values (Id, Name, Label) | none (dropdowns on `/deals`, `/reports/reporting`) | | `GET /api/v1/fund-strategies`, `/api/v1/currencies` | Fund dropdown values | none (dropdowns on `/funds`) | | `GET /api/v1/brokers` | Broker ids and names | `/deals/brokers` (Deals > Brokers), names only | | `GET /api/v1/users` | Active SUIT users (ids and names) | none (coverage dropdown on `/funds/manager-list`) | Pages that are not listed are not in the API yet (for example the pipeline snapshots, documents, contacts, underwriting and investor relations). If a request needs one of them, say so instead of using the web app. ## Parameters `GET /api/v1/reports/reporting` - `selectedDate` (yyyy-MM-dd, default today), `returnsBy` (`Deal` default, `Interest`, `Fund`, `Manager`) - `entityIds` (Banner Ridge funds: `/api/v1/entities?fundEntity=true`), `fundIds` (`/api/v1/funds/in-completed-deals`), `fundManagerIds` (`/api/v1/fund-managers/in-completed-deals`), `completedDealIds` (`/api/v1/completed-deals`), `dealTypes` (`/api/v1/deal-types`) - `closed` (default true), `pendingClose` (default false), `pendingSigning` (default false) - `sections`: the tables to return, comma separated (default all; see below) - `sortColumn` / `sortDirection` for Returns: name, firstfunding, commitment, expecteddeployment, unfunded, openingnav, openingprice, cost, netdistributions, netassetvalue, navpercentage, totalvalue (default, desc), moic, dpi, irr - `unascribedSortColumn` / `unascribedSortDirection` for Unascribed Value By Fund: name, report_date, nav_date, nav, rolled_roc_excess (default, desc), rolled_pnl_excess, mtm_roc_excess, yrs, valuexyrs `GET /api/v1/funds`: `name`, `currency` (code), `sizeMin` / `sizeMax` (full amount), `vintageYearMin` / `vintageYearMax`, `fundManagerId`, `strategyId`, `sortColumn` (updatetimestamp default, name, currency, size, vintageyear, fundmanagername), `sortDirection`, `pageNumber`, `pageSize`. `GET /api/v1/fund-managers`: `coverageUserId`, `search`, `ids`, `sortColumn` (name default, priority, fundcount, firstmeetingdate, address), `sortDirection`. `GET /api/v1/entities`: `group` (all default, ownership, investment), `fundEntity` (true / false), `primaryOnly`, `search`, `ids`, `sortColumn` (name default, ultimateparent, inactive, hedgefund, valuation, fund, date), `sortDirection`. `GET /api/v1/deals`: `name`, `dealType`, `subDealType`, `dealStrategy`, `brokerId`, `fundId`, `fundManagerId`, `seller`, `createdDateMin` / `createdDateMax` (yyyy-MM-dd), `estimatedEquityCheckMin` / `estimatedEquityCheckMax` (full dollars), `dealStage`, `ids`, `sortColumn` (updatetimestamp default, name, dealtype, brokername, sellername, pricingdate, finalbiddate, nextbiddate, estimatedequitycheck, stage), `sortDirection`. `GET /api/v1/deal-interests`: `dealId`, `fundId`, `search`, `sortColumn` (fundname default, currencycode, commitment, unfunded, netassetvalue, rofr, dealname, fundmanagername, updatetimestamp), `sortDirection`. `GET /api/v1/completed-deals`: `search`, `ids`, `sortColumn` (name default, originaldealname, brokername, updatetimestamp), `sortDirection`. `GET /api/v1/completed-deals/{completedDealId}`: `sortColumn` for its interests (fundname default, daterecord, dateagreement, datesignedpsa, datetransferred, datestatementeffective, holdername, name, originaldealname, brokername, netassetvalue, fundmanagername, commitment, unfundedcommitment, netinvestmentcost, capitalactivitytotal, expecteddeployment), `sortDirection`. `GET /api/v1/completed-deal-interests`: `completedDealId`, `fundId`, `search`, `sortColumn` (the same list without expecteddeployment), `sortDirection`. `GET /api/v1/funds/in-completed-deals` and `/api/v1/fund-managers/in-completed-deals`: `search`, `ids`. ## Common tasks Returns (NAV, MOIC, DPI, IRR) for a Banner Ridge fund as of a date: 1. `GET /api/v1/entities?fundEntity=true` and pick the entity by `Name` or `ShortName`. 2. `GET /api/v1/reports/reporting?entityIds={id}&selectedDate=2026-06-30§ions=returns` (add `returnsBy=Fund` for one row per underlying fund). The rows are in `Returns.Items`; the portfolio total is `Returns.Total`. Everything about an underlying fund: 1. `GET /api/v1/funds?name=...` (or `/api/v1/funds/in-completed-deals?search=...` for funds Banner Ridge owns). 2. `GET /api/v1/funds/{fundId}`; interests bought: `GET /api/v1/completed-deal-interests?fundId={fundId}`; offered in pipeline deals: `GET /api/v1/deal-interests?fundId={fundId}`; its returns: `GET /api/v1/reports/reporting?fundIds={fundId}§ions=returns`. What was bought in a completed deal: `GET /api/v1/completed-deals?search=...`, then `GET /api/v1/completed-deals/{completedDealId}` (interests, buying entities and their ownership, costs, net investment cost, statements, capital calls and distributions, IC memos, and a separate `Total`: Banner Ridge's purchase and the whole interests including any part the seller kept). A manager's funds and deals: `GET /api/v1/fund-managers?search=...`, then `GET /api/v1/funds?fundManagerId={id}` and `GET /api/v1/deals?fundManagerId={id}`. Pipeline deals by broker since a date: `GET /api/v1/brokers`, then `GET /api/v1/deals?brokerId={id}&createdDateMin=2026-01-01`. Turning codes into labels: `GET /api/v1/deal-types` (and the other lookup endpoints); cost and cash flow types come with names on the completed deal endpoint. ## Portfolio Reporting Data in detail `GET /api/v1/reports/reporting` runs the same portfolio calculation as the page's "Load Returns" button. It can take a while: call it once per set of filters, reuse the result, ask only for the `sections` you need, and do not run several at the same time. Money is in full amounts (the page shows it with $); percentages and IRR are fractions. Every table is an object `{ "Items": [...], "Total": {...} }`. `Items` are the rows; `Total` is the total row the page shows, with the same fields as a row, or null when the table has no total. The total is never one of the Items, so summing `Items` does not double count. Tables (`sections` value -> response property): - `returns` -> `Returns`: one row per deal (completed deal), interest, fund or manager (`returnsBy`), sorted by Total Value, plus the portfolio `Total` (its MOIC, DPI and IRR are calculated on the whole portfolio, not summed from the rows). Fields: `Name`, `ReturnsById` (the completed deal / interest / fund / manager id), `FirstFunding`, `LastFunding`, `Commitment`, `ExpectedDeployment`, `Unfunded`, `OpeningNAV` (NAV at purchase), `OpeningPrice` (price as a fraction of opening NAV), `Cost`, `NetDistributions`, `NetAssetValue`, `NAVPercentage` (share of total NAV), `TotalValue` (= NetDistributions + NetAssetValue), `MOIC` (= TotalValue / Cost), `DPI` (= NetDistributions / Cost), `IRR` (fraction; null when it cannot be calculated; 0 when profit or loss is under $100). - `netassetvaluebydate` -> `NetAssetValueByDate`: NAV by the date (and final/estimate status) of the statements it comes from. - Data Issues: `fundswithoutfundholdings` -> `FundsWithoutFundHoldings` (NAV of funds with no holdings data, by manager); `unascribedvaluebyfund` -> `UnascribedValueByFund` (value the holdings do not account for; columns as on the page); `missingfundholdings` -> `MissingFundHoldings` (funds whose latest holdings report date differs from their statement date). - Exposure by Deal: `dealsbyclosingprice` -> `DealsByClosingPrice` (deal counts by price as a percent of NAV; bounds are in percent, 100 = par), `dealsbysize` -> `DealsBySize` (deals and cost by size bucket; bucket bounds in $ millions), `quarterlydistributionsbydeal` -> `QuarterlyDistributionsByDeal` and `quarterlydistributions` -> `QuarterlyDistributions` (cumulative distributions, cost and DPI by quarter since first funding), `fundsbystrategy` -> `FundsByStrategy`, `costbystrategy` -> `CostByStrategy`. - Exposure (NAV look-through to funds and assets): `netassetvaluebyvintage`, `netassetvaluebygp` (top 10 + Other + Total), `netassetvaluebyfund` (top 10), `netassetvaluebyasset` (top 10 portfolio companies), `netassetvaluebyindustry` (top 15), `netassetvaluebygeography` -> the matching `NetAssetValueBy...` property. Rows have `Name`, `Value`, `Percentage` (fraction of total), `Rank` and `IsOther` (the "Other" row is one of the Items, so the Items add up to the Total). - `dealsreviewed` -> `DealsReviewed`: pipeline deals reviewed since the fund's inception - only when exactly one `entityIds` value is given. The response also echoes the filters used (`Filters`) and the sorts applied. ## Tips - Resolve names to ids with the list endpoints (`search` / `name` parameters) before calling the detail or report endpoints. - Prefer filters over downloading everything; most lists are small, but `/api/v1/funds` and `/api/v1/completed-deal-interests` can be large. - When quoting numbers to people, format them yourself (currency, %, x) and say which date the data is as of. - Data is live: each call reads the current SUIT database.