Check any company's public trust signals from its domain
The Business Trust API returns a trust signal for a business as clean JSON.
2 active endpoints, on 7 and 24 credit tiers.
- POST/enrich-trust/v1/business_trust
- POST/enrich-trust/v1/batch
What Business Trust endpoints does ReefAPI ship?
2 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.
Business Trust API
2 of 2 endpoints, ready to run
A four-value recommendation plus three lists — what is positive, what is a risk, and what could not be checked — each entry carrying a code, a label, its evidence and the source it came from.
{ "ok": true, "meta": { "api": "business-trust", "endpoint": "business_trust", "mode": "live", "latency_ms": 5170.6, "record_count": 6, "cache_hit": false }, "data": { "entity": { "input": "stripe.com", "kind": "domain", "match": "exact-domain", "confidence": 0.9, "canonical_name": "Stripe", "country": null, "evidence": [ { "name": "Stripe", "kind": "trustpilot-domain-match", "source": "trustpilot" } ] }, "recommendation": "proceed", "score_method": "heuristic_signal_summary_v1", "positive_signals": [ { "code": "domain_age_mature", "label": "Domain established 31.0+ years", "evidence": "age_days=11308 (band=mature)", "source": "domain-risk" }, { "code": "ssl_present", "label": "Valid TLS certificate present", "evidence": "has_certificate=true", "source": "domain-risk" }, { "code": "email_authenticated", "label": "Authenticated business email (SPF+DMARC)", "evidence": "mx+spf+dmarc present", "source": "domain-risk" } ], "risk_signals": [], "unknowns": [ { "code": "web_presence", "label": "Indexed web presence", "reason": "unsupported", "source": "google-search" }, { "code": "sanctions", "label": "Sanctions / watchlist screening", "reason": "not_checked", "source": "out-of-scope" }, { "code": "regional_reputation", "label": "Region-routed reputation (Yelp/TripAdvisor/ReclameAqui/Naver)", "reason": "not_checked", "source": "depth=basic" } ], "reputation": { "trustpilot": { "found": true, "domain": "stripe.com", "matched_on": "domain-match", "name": "Stripe", "trust_score": 1.6, "stars": 1.5, "reviews_count": 17453, "categories": [ "Payment Service" ], "rating_note": "1.5/5 over 17453 reviews — public review rating; review scores reflect self-selected reviewers and are NOT a fraud/risk signal." }, "maps": { "found": true, "match": "domain", "name": "Stripe Toronto Office", "rating": 3.2, "review_count": 4, "address": "1 University Ave, Toronto, ON M5J 1S8, Canada", "category": "Business development service", "website": "https://stripe.com/en-ca" } }, "domain_signals": { "age_days": 11308, "age_years": 30.96, "age_band": "mature", "expiry_risk": "ok", "recently_registered": false, "registrar": "SafeNames Ltd.", "has_certificate": true, "dnssec": false, "mail": { "mx": true, "spf": true, "dmarc": true }, "parked": false, "for_sale": false, "impersonation": null, "risk_level": "low" }, "presence": { "own_site_indexed": false }, "region": { "country": null, "routing": "global (trustpilot/maps/search)" }, "scope": { "kyb_aml": "out-of-scope", "sanctions": "not-checked (gov-pending)", "person_pii": "excluded" }, "disclaimer": "Public trust-signals only. This is NOT KYB/AML, sanctions screening, or credit/identity verification, and is not an approve/reject decision. Signals are derived from public sources and may be incomplete or out of date; verify independently before acting. Company-level public data only — no personal data.", "assessed_at": "2026-08-28T21:18:04Z" } }
How the Business Trust API works
Business Trust is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.
No OAuth app, no request signing, no per-site account. One key covers all 184 engines.
Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.
Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.
One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.
Read the evidence, not the verdict
The recommendation is a triage label, and the response says so itself. Everything that would let you defend a decision is in the three signal lists underneath it.
{"domain": "stripe.com"}Domain in, six positive signals out, each with the measurement behind it: domain age in days, certificate present, mail authentication, news scan, physical listing.
Never act on the verdict alone. A negative-news hit carries the headline that triggered it, and a brand can appear in a security story as the victim rather than the actor.
Not-checked is not a pass. Sanctions screening in particular is explicitly out of scope here and is named as an unknown on every call.
One credit for a defensible onboarding signal. The batch action runs a supplier list through the same path in a single call.
curl -X POST https://api.reefapi.com/enrich-trust/v1/business_trust \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"domain":"stripe.com","depth":"basic"}'{
"ok": true,
"data": { … },
"meta": {
"api": "enrich-trust",
"endpoint": "business_trust",
"mode": "live",
"latency_ms": …,
"record_count": …
},
"error": null
}There is no trust score here, and that is deliberate
This engine does not return a number. It returns three lists (positive_signals, risk_signals, unknowns), a four-value recommendation, and a score_method string that reads "heuristic_signal_summary_v1". If you want a 0-100 figure, its siblings have one: enrich-package for a package, enrich-app for an app's reputation index, email-health for a sending domain. Everything below was measured on stripe.com, cloudflare.com, Trendyol, an unregistered domain and a made-up company name.
| Field | Measured values | What to know |
|---|---|---|
| recommendation | proceed / review / high_risk / insufficient_data | the only verdict field; there is no numeric score to threshold on |
| entity.match + confidence | "exact-domain" 0.9 / "fuzzy" 0.5 / "fuzzy" 0.3 | 0.9 came with evidence kind "trustpilot-domain-match"; 0.5 is a name-only input echoed back; 0.3 was a stem guess off an unregistered domain |
| reputation.trustpilot.matched_on | "domain-match" / "domain-stem-match" / absent when found is false | When both sides know a domain, the domains decide: stripe.com matched its own record as domain-match, allbirds.co.uk matched the allbirds.com record as domain-stem-match, and a small firm with no review presence returned found:false reason not_found rather than a same-named stranger's score |
| positive_signals[].code | domain_age_mature, ssl_present, email_authenticated, review_volume, no_negative_news, real_world_presence, app_store_presence | app_store_presence appeared only at depth rich; each row carries label, evidence and source |
| risk_signals[].code | domain_unregistered, negative_news | an unregistered domain produced exactly one risk row and a "review" verdict |
| unknowns[].reason | not_checked / not_found / not_applicable / unsupported | a sanctions row with reason "not_checked" is present in every response we made, without exception |
| domain_signals | age_days 11306, age_band "mature", registrar, has_certificate, dnssec, mail{mx,spf,dmarc}, parked, for_sale, risk_level | for a name-only input this object is empty and unknowns gains domain_lifecycle "not_applicable" |
| reputation.trustpilot.rating_note | "1.5/5 over 17438 reviews - public review rating; review scores reflect self-selected reviewers and are NOT a fraud/risk signal" | the note ships with the number so a low rating cannot be read as a risk finding |
| depth | basic / rich | rich adds rating_distribution, is_claimed and sample_reviews to Trustpilot plus region-routed sources; the top-level shape does not change |
| meta.record_count | 6 for stripe.com, 3 for Trendyol, 0 for a made-up name | it counts positive_signals, so a 0 means no positive signal resolved, not an empty response |
Scope is stated in the payload rather than only in the docs. Every response carries scope {kyb_aml: "out-of-scope", sanctions: "not-checked (gov-pending)", person_pii: "excluded"} and a disclaimer saying this is not KYB, AML, sanctions screening, credit or identity verification, and not an approve or reject decision. business_type is a hint that suppresses false risks rather than a filter: passing b2b means an absent public review presence is treated as normal, and country drives which regional reputation sources are consulted (measured TR routing on a Trendyol lookup).
What it checks, what it refuses to claim, and how it matches
Measured against two large domains, an unregistered domain, a name-only input and one company looked up both ways, then re-measured after the review matching was rewritten. The first row is the reason to pass a domain.
Two real domains resolved at entity confidence 0.9 with six positive signals each. The same company looked up by NAME resolved at 0.5 with two positive signals and four unknowns. The name path cannot see domain age, certificates or mail authentication, which is most of what the engine is for.
reputation.trustpilot now carries matched_on, and when both sides know a domain the domains decide. A payments company matched its own domain and reported domain-match. A British storefront asked about allbirds.co.uk matched the record filed under allbirds.com and said so with domain-stem-match — same brand, other country — rather than pretending it was an exact hit. A small coffee company with no review presence returned found:false with reason not_found instead of a same-named stranger's score, which is what it used to do. Read matched_on before you use the number.
Every response carries a scope block and a disclaimer stating in plain words that this is not KYB, not AML, not sanctions screening, not credit or identity verification, and not an approve or reject decision. Sanctions is listed under unknowns on every single call. If you need that check, it is a different endpoint and a different question.
An unregistered domain returned recommendation review, confidence 0.3, zero positive signals and one risk signal reading domain_unregistered. Not an error, not an empty object — a verdict with the reason attached.
Domain age in days with a band, certificate presence, MX plus SPF plus DMARC, registrar, DNSSEC, parked and for-sale flags, an expiry-risk label and a count of news articles scanned. Every entry names its source. The score method string is published on the response so you know it is a heuristic summary and not a model.
On a domain with an app and a real review history, rich added a seventh positive signal for app-store presence and gave the review block three more fields: a claimed flag, the full star distribution and sample reviews — in 4.4 seconds against 2.9 for basic. On a small company with eight reviews and no app it took 32.7 seconds and returned exactly the same six signals and the same sources. rich is worth it when there is something extra to find, and it is the slower call when there is not.
What people build with Business Trust
The jobs this data is most often used for.
endpoints
credits per call
Marketplaces call business_trust to vet a seller's legitimacy at onboarding.
Trust-and-safety teams score a merchant against multiple signals.
Due-diligence workflows use batch to screen many businesses at once.
What Business Trust data costs
The cheapest call here is 7 credits, so $15/mo (Pro) buys 1,428 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.
Full pricing →- 1,000 free credits on signup, no card
- One key, all 184 APIs, one credit pool
- Failed and blocked calls are never charged
- Credits roll over and never expire
Call it in two lines
Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.
curl -X POST https://api.reefapi.com/enrich-trust/v1/business_trust \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"domain":"stripe.com","depth":"basic"}'import requests
r = requests.post(
"https://api.reefapi.com/enrich-trust/v1/business_trust",
headers={"x-api-key": REEF_KEY},
json={
"domain": "stripe.com",
"depth": "basic"
},
)
print(r.json()["data"])Have a question? We got answers.
The questions people actually ask before wiring up Business Trust.
Get a free key →Stripe has 1.5 stars on Trustpilot. Why does the verdict still say proceed?▾
Because a public review rating is not treated as a risk signal. A measured stripe.com lookup returned trust_score 1.6, stars 1.5, reviews_count 17438 and recommendation "proceed", and Trustpilot's presence entered the positive list as review_volume, "Established review presence (17438 reviews)". The response even ships a rating_note saying review scores reflect self-selected reviewers and are not a fraud signal. Volume of public reviews is the signal; the star average is context you can display but should not threshold on.
A well-known company came back as "review". What triggers that?▾
One entity-matched negative news article is enough. A measured cloudflare.com lookup returned five positive signals and recommendation "review", with a single risk_signals row whose evidence was the headline "24 npm Packages Abuse unpkg Mirrors to Host Fake Cloudflare CAPTCHA Pages". Cloudflare is the impersonated party in that story, not the actor, and the matcher does not make that distinction. Always read risk_signals[].evidence before acting on a "review", especially for security vendors and large brands that appear in incident coverage about other people.
What comes back for a business that does not exist?▾
ok:true with the emptiness made explicit, in two different shapes. A made-up domain returned recommendation "review", zero positive signals and one risk row, domain_unregistered, with evidence "registered=false / available=true; no live web/DNS/reputation evidence found". A made-up company name returned recommendation "insufficient_data", meta.record_count 0, empty positive and risk lists, and six unknowns rows naming what could not be checked. Nothing was substituted for the input in either case.
entity.confidence came back 0.5 for a company I invented. Does that mean it half-exists?▾
No. For a name-only input, confidence 0.5 with evidence kind "input-name" and source "input" simply means the engine echoed your string back as the canonical name, because there was nothing else to resolve against. We measured exactly 0.5 for both a real brand and an invented one. The number that carries information is 0.9 with match "exact-domain", where the evidence names a real source. Read entity.evidence[].kind, not the number alone.
Does this do sanctions, KYB or AML screening?▾
No, and it says so in every response rather than leaving it to the small print. unknowns always contains a row with code "sanctions", label "Sanctions / watchlist screening", reason "not_checked", source "out-of-scope", and the scope object repeats it as "not-checked (gov-pending)". We saw that row in every call we made, including on stripe.com where six positive signals resolved. Use this to triage a merchant or counterparty quickly; use a regulated provider for the compliance decision.
Which of the enrich engines should I actually call?▾
They divide by question, not by subject. enrich-company turns a domain into facts (WHOIS, DNS, SSL, tech stack, Tranco rank, Wikidata). enrich-store answers what e-commerce platform a storefront runs and what its catalog looks like. enrich-local matches a business to a Google Maps place. enrich-app scores an app's public reputation. enrich-trust sits on top and answers one different question: given the public signals, should a human look at this before you transact. It calls several of the others internally and then makes a judgement they do not make.
Does business_type change the verdict or just the wording?▾
It changes which absences count against you. The enum is auto, local, ecommerce, saas, brand and b2b, and the documented effect is that b2b treats a scarce public review presence as normal rather than as a risk. Similarly country, an ISO-3166 alpha-2 hint, routes which regional reputation sources are consulted and stops an absent US-only source from reading as a risk abroad; a Trendyol lookup with country TR returned region.routing "TR to trustpilot/maps/search". When omitted, country is inferred from the ccTLD.
Why does presence.own_site_indexed say false for a major site?▾
Because the indexed-web-presence check is currently unavailable, not because the site is missing from search. A measured stripe.com response carried presence.own_site_indexed false while unknowns listed code "web_presence" with reason "unsupported". The engine is honest about it in the unknowns list rather than converting the gap into a risk signal, and no risk row was raised. Read unknowns first; a false in presence is not a finding when the matching unknowns row says unsupported.
What is the Business Trust API?▾
Business Trust API is a ReefAPI endpoint group for business trust It returns live JSON through POST requests under /enrich-trust/v1.
Is the Business Trust API free to try?▾
Yes. ReefAPI starts with 1,000 free credits, no card required. Business Trust calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Business Trust login or account?▾
No login to Business Trust is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Business Trust data?▾
The page example is captured from a live business_trust call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Business Trust API use?▾
Business Trust actions currently cost 7-24 credits per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call Business Trust from an AI assistant or MCP client?▾
Yes. Connect ReefAPI once through MCP and your assistant can call enrich-trust actions with the same key, credit pool and JSON envelope used by normal REST requests.
14 Reputation & Reviews APIs on the same key
One key, one credit pool, one response envelope. If you are pulling Business Trust, you are one call away from the rest of the category — no second contract, no second integration.
Need something this API does not do?
Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.
Try it on your own data before you pay anything
The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 183 APIs, and the same envelope everywhere.
Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-28.