BMarker report API

Send a transaction log, run BMarker's portfolio analysis, and receive a branded report. API access is included with BMarker Pro.

POSThttps://bmarker.com/api/v1/reports

Get started

  1. 1
    Activate BMarker Pro.

    The report endpoint is available to workspaces with an active Pro plan.

  2. 2
    Create an API key.

    Open Settings → Report API keys, name the key, and copy its secret.

  3. 3
    Send the key with each request.

    Store it with your application secrets and use the Bearer header below.

Authorization headerAuthorization: Bearer bmk_live_your_key

Request and output examples

Choose an output type to update the request and preview its response. Each downloadable artifact is generated from this request through the same report pipeline used by the API.

report.json
{
  "analysis": {
    "analysisWindow": null,
    "balanceNormalization": "enabled",
    "regressionWindow": null,
    "rollingWindow": 126
  },
  "branding": {
    "accentColor": "#0c6748",
    "logoDataUrl": null,
    "name": "Example Capital",
    "showBmarker": false,
    "websiteUrl": "https://example.com"
  },
  "format": "html",
  "portfolio": {
    "benchmarkSymbol": "SPY",
    "currency": "USD",
    "name": "Long-term portfolio"
  },
  "pricing": {
    "mode": "completed-close"
  },
  "presentation": {
    "balancePrivacy": true,
    "shareTransactionNotes": false,
    "showHoldings": true,
    "showTrades": true
  },
  "themeOverrides": {
    "light": {
      "colors": {
        "accent": "#147a5c",
        "background": "#f7f8f6",
        "border": "#d5dcda",
        "muted": "#60615f",
        "negative": "#c84634",
        "positive": "#147a5c",
        "surface": "#ffffff",
        "text": "#171717"
      },
      "font": "modern",
      "radius": "soft"
    }
  },
  "theme": "light",
  "title": "Portfolio performance report",
  "transactions": [
    {
      "date": "2026-01-05",
      "fees": "1",
      "notes": "Opened the position",
      "price": "267.26",
      "quantity": "10",
      "symbol": "AAPL",
      "type": "BUY"
    },
    {
      "date": "2026-03-02",
      "fees": "0.5",
      "notes": "Trimmed the position",
      "price": "264.72",
      "quantity": "2",
      "symbol": "AAPL",
      "type": "SELL"
    }
  ]
}
Rendered HTML
Open the full HTML example →
cURL
curl --request POST https://bmarker.com/api/v1/reports \
  --header "Authorization: Bearer $BMARKER_API_KEY" \
  --header "Content-Type: application/json" \
  --data @report.json \
  --output portfolio-report.html

Change format and the output filename to create PDF, XML, or JSON.

Request fields

Send UTF-8 JSON with Content-Type: application/json. Prices, quantities, and fees accept JSON numbers or decimal strings. Supply transactions as either structured JSON rows or CSV text inside the JSON request.

Top-level fields

FieldRequiredDescription
formatYeshtml, pdf, xml, or json.
portfolioYesThe portfolio name, currency, and benchmark ticker.
transactionsOne input requiredAn array containing one or more BUY or SELL records.
transactionsCsvOne input requiredCSV text with date, type, symbol, quantity, and price headers. fees and notes are optional. Use this instead of transactions.
analysisNoAnalysis, regression, rolling, and balance-normalization settings.
pricingNoControls whether the report includes live or completed-close prices.
presentationNoBalance privacy, holdings, trades, and transaction-note settings.
titleNoUp to 140 characters. Defaults to “Portfolio performance report.”
brandingNoA display name, accent color, and website link.
themeNolight or dark. Defaults to light and sets the default HTML and PDF theme.
themeOverridesNoOptional light and dark color, font, and corner-radius overrides for matching an embedding site.

CSV transactions

Put RFC 4180-compatible CSV text in transactionsCsv. Header names are case-insensitive, quoted values may contain commas or line breaks, blank fees default to zero, and blank notes become null. All other report fields stay the same, so CSV input supports every analysis, presentation, branding, and output option available to structured transaction rows.

transactionsCsv value
date,type,symbol,quantity,price,fees,notes
2026-01-05,BUY,AAPL,10,267.26,1,Opened the position
2026-03-02,SELL,AAPL,2,264.72,0.5,Trimmed the position

Portfolio and analysis

FieldAccepted values
portfolio.name1–100 characters.
portfolio.currencyA three-letter code. Defaults to USD.
portfolio.benchmarkSymbolA ticker up to 20 characters. Defaults to SPY.
analysis.analysisWindownull, 21, 63, 126, or 252. Null uses all available history.
analysis.regressionWindownull, 21, 63, 126, or 252. Null uses the full analysis span.
analysis.rollingWindow21, 63, 126, or 252. Defaults to 126.
analysis.balanceNormalizationenabled or disabled. Defaults to enabled.

Pricing

Set pricing.mode to live or completed-close. The default is live.

ModeBehavior
liveUses completed daily closes and may add current-session prices when live pricing is enabled for the workspace. Extended-hours prices follow the workspace setting.
completed-closeUses the most recent fully completed market session. Intraday and extended-hours price requests are disabled, and the complete report is generated from completed closes.

Presentation

These fields are passed to the shared report component used by public share pages. The defaults match a new share page.

FieldDefaultUse
presentation.balancePrivacytrueShows return, benchmark, excess-return, and drawdown cards. Set to false to show current value, net invested, gain/loss, and portfolio return.
presentation.showHoldingsfalseAdds current holdings and holdings-over-time sections.
presentation.showTradesfalseAdds the trade-activity section.
presentation.shareTransactionNotesfalseIncludes transaction notes when trade activity is shown.

Theme

Set the root theme field to light or dark to choose the default style for HTML and PDF reports. A self-contained HTML report can override that choice when embedded by adding ?theme=light or ?theme=dark to its URL.

Use themeOverrides when a report is embedded in another site and its light or dark palette should match the host. Each mode may provide any subset ofcolors ( accent, background, border, muted, negative, positive, surface, and text), plus font ( system, modern, or editorial) and radius (sharp, soft, or round). Unspecified values keep the selected built-in theme.

themeOverrides example
{
  "themeOverrides": {
    "light": {
      "colors": {
        "accent": "#147a5c",
        "background": "#f7f8f6",
        "border": "#d5dcda",
        "muted": "#60615f",
        "negative": "#c84634",
        "positive": "#147a5c",
        "surface": "#ffffff",
        "text": "#171717"
      },
      "font": "modern",
      "radius": "soft"
    }
  }
}

Branding

Branding appears in the HTML and PDF header and is included in the XML and JSON report envelope. When branding is omitted, the report uses “Portfolio report” and BMarker green.

FieldDefaultUse
branding.namePortfolio reportA 1–100 character brand name shown in the report header.
branding.websiteUrlnullAn HTTP or HTTPS link for the brand name and logo. Credentials in the URL are rejected.
branding.accentColor#0c6748A six-digit hex color used for report accents and positive values.
branding.logoDataUrlnullA base64 PNG, JPEG, or WebP data URL up to 350,000 characters. The header uses the first letter of the brand name when this is null.
branding.showBmarkerfalseSet to true to add the “Powered by BMarker” footer.

A logo value begins with a media prefix such asdata:image/png;base64,, followed by the image's base64 data. PNG, JPEG, and WebP signatures are checked before the report is generated.

Transaction fields

FieldRequiredDescription
dateYesA real calendar date in YYYY-MM-DD form.
typeYesBUY or SELL.
symbolYesA ticker up to 20 characters.
quantityYesA decimal value greater than zero.
priceYesThe execution price, greater than zero, or open or closeto use that ticker's unadjusted daily price on the transaction date.
feesNoA decimal value of zero or greater. Defaults to zero.
notesNoUp to 500 characters, or null.

Report data

BMarker loads completed daily closes, applies stock splits, repairs missing close ranges, and runs the same transaction-aware performance engine used by the app. Live-mode reports may also include the current market session. QuantStats supplies the deeper risk and benchmark-relative analytics.

FieldContents
performanceSummary, timeframe returns, holdings, daily series, cumulative growth, excess return, alpha, balance, and holdings history.
analyticsCalculation parameters, Sharpe, Sortino, CAGR, volatility, drawdowns, capture, correlation, calendar returns, distributions, and rolling series.
intradayThe live price snapshot and current portfolio valuation, including market session, prior-close growth, quote freshness, and fallback symbols. Its enabled field is false for completed-close reports.
pricingThe requested pricing mode used to generate the report.
effectiveWindowsThe analysis and regression windows supported by the available observations.
excludedSymbolsSymbols that could not be analyzed, with reasons and affected transaction row IDs.
transactionsThe normalized transaction rows used by the analysis.
themeThe requested default theme: light or dark.

Historical returns and risk metrics have a completed-close timestamp inperformance.summary.asOf. Current valuation comes fromintraday.valuation, with quote details in intraday.snapshot. HTML and PDF show that value and its prior-close growth when pricing.mode is live, intraday.enabled is true, andpresentation.balancePrivacy is false.

Formats

A successful response has status 200 and a filename in theContent-Disposition header, such aslong-term-portfolio-performance.pdf.

FormatContent-TypeContents
htmltext/htmlA self-contained share-page report with embedded styles.
pdfapplication/pdfA print rendering of the same HTML report.
xmlapplication/xmlThe complete report envelope as XML.
jsonapplication/jsonThe complete report envelope as JSON.

Errors

Error responses use JSON. Every response has an X-Request-ID header; error bodies repeat it as requestId for support requests.

Error response
{
  "error": {
    "code": "invalid_request",
    "message": "transactions.0.date: Use a real calendar date."
  },
  "requestId": "87a20465-1b42-4d85-9305-55467b783064"
}
StatusMeaning
400The JSON or one of its fields is invalid.
401The API key is missing, malformed, deleted, or unknown.
403The key lacks report permission or the workspace needs an active Pro plan.
413The request body exceeds 2 MiB.
415The Content-Type header must be application/json.
422The transactions could not produce an analyzable portfolio report. The body includes the performance issues.
429The market-data provider is rate limited.
503Market data, analytics, or the report renderer is temporarily unavailable.
504Analytics or PDF rendering timed out.

API keys

The full key appears once when it is created. Give each integration its own key so its access can be managed independently.

Roll creates a replacement while the current key stays active. Update the integration, confirm a successful request, and delete the previous key. Deletion takes effect immediately.

Manage API keys →

Limits

  • At least one transaction per report.
  • Up to 250 unique transaction symbols per API report.
  • 2 MiB maximum request body.
  • Up to 12 decimal places in decimal-string inputs.

JSON arrays and embedded CSV share the 2 MiB request allowance. For larger reports, contact contact@bmarker.com.