MARBIN ← DevelopersAPI guideBack to marbin.co.uk
MARBIN · Core API 1.4

Shariah-first research, by API

MARBIN's Shariah-first research engine, read-only: the Shariah screen with its ratios and method, purification, zakat, the market reading, entry signals and the long-term model portfolio. Data and methodology, not investment advice; the screen is mechanical, not a fatwa. The API never trades and never holds anyone's broker key. A white-label bank's own systems also run its customers here (the customer and account API, below): machine sign-in, one bank only.

Keys

Full keymk_live_…For your server. Send it as Authorization: Bearer. Every endpoint.
Widget keymk_pub_live_…Safe in a web page. Screen, purification and zakat only, and only from the websites listed on the key.
Sandbox keymk_sandbox_…Sample figures for building and testing. Every endpoint; every answer is marked as sample data.

Each key has its own requests-a-minute limit. Calls are logged by key, endpoint and status, never with the key or the answer. To get a key, write to [email protected].

Endpoints

GET /v1/healthno key

Is the engine running?. Heartbeat, last scan and stocks covered. No key needed.

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/health"

GET /v1/universe

Stocks covered. Every stock the engine follows, with its Shariah status and when it was last checked.

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/universe"

GET /v1/screen/{symbol}widget

Shariah screen for one stock. The verdict with its evidence: business activity, debt and cash against the 24-month average market value, interest income against revenue, the limits used and the method. A key carrying the client's own Shariah limits gets the verdict decided by those limits.

Parameters: symbol

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/screen/AAPL"

GET /v1/screenwidget

Shariah screen for many stocks. Up to 50 symbols a call, in one answer.

Parameters: symbols

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/screen?symbols=AAPL,MSFT,NVDA"

GET /v1/purification/{symbol}widget

Purification. The share of each dividend to give away (the company's interest income as a share of its revenue). Add dividend= to get the amount.

Parameters: symbol, dividend

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/purification/AAPL?dividend=120"

GET /v1/zakatwidget

Zakat on a portfolio. Zakat at 2.5% two common ways: every share at market value (market_value), and each share at its company's own zakatable assets -- cash, short-term investments, receivables and inventory per share from its latest balance sheet, against its price (company_assets; AAOIFI Shariah Standard 35), a quarter of the value where a company's figures are missing (named in proxied). The live nisab (85 g gold, 595 g silver) in the currency asked for. Each holding's Shariah status and zakatable share come back too. quarter_rule (the older flat 25%) is kept for version 1.3's clients.

Parameters: holdings, cash, currency, standard

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/zakat?holdings=AAPL:5000,MSFT:2500&cash=1000"

GET /v1/market

Market reading. Index trends against their 200-day averages, and the VIX fear gauge.

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/market"

GET /v1/signals

Entry signals. Stocks that passed every gate at the last scan, best score first.

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/signals"

GET /v1/model/core

Long-term model portfolio. The holdings MARBIN's rules pick today, with the rules.

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/model/core"

GET /v1/filings/{symbol}

Company filings red flags. US companies: SEC 8-K red flags (bankruptcy, triggering events, delisting, restated results) and insider buying and selling over 90 days, sales after exercising options counted apart. The engine checks its watchlist twice a day; covered=false for a company with no SEC filings. Shown, not acted on.

Parameters: symbol

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/filings/AAPL"

GET /v1/track-record

How MARBIN's forecasts have done. From the forecast ledger: each kind of forecast (the return model, the MARBIN score, analysts' price targets, the risk score) at each horizon, checked against what happened -- rank correlation with the outcome (mean_ic), top-minus-bottom fifth (spread_pct), analysts' hit rates. Past results are no guide to the future.

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/track-record"

GET /v1/history

What the history holds. The dates covered, the stocks, the exchange-rate pairs and every field a stock's daily reading has.

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/history"

GET /v1/history/fields

What every history field means. Each field a stock's daily reading can carry, with its unit, and the fields sent when fields= isn't given.

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/history/fields"

GET /v1/history/{symbol}

One stock's daily readings. The engine's closing reading of a stock on each day: price and technicals, MARBIN score and risk score (with their parts), stop and target, forecast, analysts, the Shariah verdict and ratios, fundamentals, filings red flags and insider selling. fields= picks columns (or all); 30 days by default, up to 400.

Parameters: symbol, from, to, fields

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/history/AAPL?from=2026-10-01&fields=score,risk_score,shariah_passed"

GET /v1/history/day/{date}

Every stock on one day. The whole universe's reading on one day.

Parameters: date

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/history/day/2026-10-02?fields=score,risk_score"

GET /v1/history/market

The market by day. The VIX and each index against its 200-day average.

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/history/market?from=2026-10-01"

GET /v1/fx/{pair}

Exchange rates by day. Daily closing rates, e.g. GBPUSD.

Parameters: pair

curl -H "Authorization: Bearer $MARBIN_KEY" \
  "https://api.marbin.co.uk/v1/fx/GBPUSD?from=2026-09-01"

Widget for your website

A zakat and purification calculator in your own page, with a widget key that lists your website:

<div data-marbin-zakat data-key="mk_pub_live_…"></div>
<div data-marbin-purify data-key="mk_pub_live_…"></div>
<script src="https://api.marbin.co.uk/widget.js" async></script>

Plans

Trial1,000 checks a month (25 assets, once a day)free
Starter7,500 checks a month (100 assets, 3 times a day)£250 a month, in advance; beyond that, £30 per 1,000 checks from prepaid credit
Growth35,000 checks a month (500 assets, 3 times a day)£900 a month, in advance; beyond that, £22 per 1,000 checks from prepaid credit
Professional180,000 checks a month (2,000 assets, 4 times a day)£2,500 a month, in advance; beyond that, £12 per 1,000 checks from prepaid credit
Enterpriseunlimited checks (the whole universe, any rate)£5,000 a month, in advance
Widget20,000 checks a month (a website's zakat and purification calculators)£50 a month, in advance; beyond that, £2.5 per 1,000 checks from prepaid credit

Plans are paid in advance, month by month, and count checks: one per asset answered -- a screen of 50 stocks is 50 checks, a zakat sum one per holding, a day's history one per stock; other answers one each. Every answer says how many it counted (checks). Refused requests never count. Beyond a plan's monthly checks, each is paid from your prepaid credit at the plan's rate; with no credit left the request is refused (429) until you top up. Trial and sandbox stop at theirs.

Versions and changes

Everything under /v1 stays compatible: fields and endpoints may be added, never removed or changed in meaning. A breaking change comes as /v2, announced at least six months before /v1 retires. Every answer carries api_version.

Keys can be rotated: the new key works at once, the old one for the overlap chosen (up to 14 days). The API guide covers keys, every endpoint, errors, rate limits, webhooks (signed notifications to your systems) and the sandbox.

For banks: customers and accounts

A white-label bank's own systems onboard, list, follow and pause its customers, at their own address, https://bank-api.marbin.co.uk (not this one). Machine sign-in is OAuth 2.0 client credentials: MARBIN gives the bank a client id and secret (only a fingerprint of the secret is kept; it can be rotated with a 7-day overlap); POST /v1/oauth/token swaps them for a token that lives 15 minutes and carries only the scopes asked for. A client sees its own bank's customers only -- another bank's are "not found". Every call needs its scope and the client's bank role, and every call, refused ones too, is in the bank's audit log. Every POST needs an Idempotency-Key header. Errors are always {"error": {"code", "message"}, "request_id"}; a method a path doesn't take is 405 method_not_allowed with an Allow header (no CORS: it's for the bank's servers). Wrong secrets back off the address sending them (429 slow_down with Retry-After); the right secret from the bank's own address still works. Money figures are after costs, as on the customer's own page; each account says whether it is live or practice, and the two are never added together. On request, mutual TLS at the edge in front of the same flow.

curl -u "$CLIENT_ID:$CLIENT_SECRET" -d grant_type=client_credentials -d "scope=customers:read accounts:read" \
  "https://bank-api.marbin.co.uk/v1/oauth/token"
curl -H "Authorization: Bearer $TOKEN" "https://bank-api.marbin.co.uk/v1/customers?status=approved&limit=50"

Many customers at once: POST /v1/customers/batch, up to 500 a call, one result per customer (invited, or rejected and why); the invitation emails go out in the background. The bank's staff can do the same from a CSV file in the partner portal (Customers, Invite in bulk).

Brokers: MARBIN sets which brokers each bank's customers may connect. POST /v1/customers answers them (brokers: allowed and the bank's default -- only brokers a customer can connect on the bank's portal today); when none can be connected on the bank's portal, onboarding is refused with 409 no_broker_allowed. A customer already connected keeps their broker.

POST /v1/oauth/token

Machine sign-in: an access token. OAuth 2.0 client credentials (RFC 6749 section 4.4). Send the client id and secret MARBIN gave the bank -- HTTP Basic (preferred) or client_id and client_secret in the form -- with grant_type=client_credentials and, optionally, scope (space-separated, at most the client's). The token lives 15 minutes; ask for a new one when it runs out. Errors here are RFC 6749's: {error, error_description}.

GET /v1/customerscustomers:read

The bank's customers. Paged, oldest id first: limit (1-200, default 50) and the next_cursor of the page before. Filters: status, kind (live or practice: the main account's), email, external_id. Removed customers only with status=removed. Scope: customers:read.

POST /v1/customerscustomers:write

Onboard a customer. An invitation in the bank's name, pending until approved: emailed to the customer in the bank's name (powered by MARBIN) unless send_invitation is false, and their email queued for the bank portal's sign-in list (sign_in_access). The customer signs in on the bank's portal with this email, connects their own broker account and makes their choices, then the bank approves them. Record the bank's own customer check (bank_check) and customer number (external_id) here if they're ready. One person, one provider: an email already with MARBIN or another provider is refused (409 already_with_another_provider, never which), and so is a new customer over the bank's customer limit (409 over_customer_limit). Scope: customers:write.

POST /v1/customers/batchcustomers:write

Onboard customers in bulk. Up to 500 customers in one call, each checked as POST /v1/customers checks one and as the partner portal's Invite in bulk checks a line: a bad email or name, the same email or external_id twice in the request, already the bank's customer, already with MARBIN or another provider (never which), over the bank's customer limit. The ready ones are invited at once (pending until approved, their sign-in access queued); their invitation emails go out in the background at about 2 a second (send_invitations: false to leave them to the bank). One result per customer, in the request's order: a rejected one changes nothing; the call answers 200 whatever the mix. A retry with the same Idempotency-Key gets the same answer and invites no one twice. Scope: customers:write.

GET /v1/customers/{customer_id}customers:read

One customer. With their accounts, each live or practice. Scope: customers:read.

POST /v1/customers/{customer_id}/bank-checkcustomers:write

Record the bank's own customer check. Before approval (invited or registered): the reference of the bank's own customer check, who did it and when. Shown to the bank's staff; MARBIN's approval flow is unchanged. Scope: customers:write.

GET /v1/accounts/{account_id}/holdingsaccounts:read

What MARBIN holds in an account. Each holding and the totals after costs, in the account's currency: total_cost = paid + buying costs; gain = value - total_cost; if_sold_today also takes off a sale's estimated costs. The same figures as the customer's own page and app. Scope: accounts:read.

GET /v1/accounts/{account_id}/performanceaccounts:read

How an account has done. Time-weighted returns against funds the customer could hold instead (day, week, month, year to date, since start), and the money made: holdings after buying costs, sales net of selling costs. Past results are no guide to the future. Scope: accounts:read.

POST /v1/accounts/{account_id}/pauseaccounts:pause

Pause an account. No new trades; the stops on its holdings stay. One person is enough: a safety action never waits. Scope: accounts:pause.

POST /v1/accounts/{account_id}/resumeaccounts:pause

Resume a paused account. Only a paused account (never an approval). Dual control -- one approver at MARBIN and one at the bank -- will apply here once it's switched on; today the client's bank role is the guard. Scope: accounts:pause.

Machine-readable

/v1/openapi.json describes every endpoint (OpenAPI 3).