opentrust.in/docs

API docs

A small JSON API. Base URL https://opentrust.in/api/v1. Create your key from your dashboard.

Libraries

Small, dependency-free clients that wrap this API with typed errors, so you can be up and running in a few lines. They're open source.

The Ruby and Node packages are about to be published. Until then you can call the API directly with any HTTP client, as shown below.

Ruby · gem
gem install opentrust

client = OpenTrust::Client.new
client.lookup("9876543210").reported?
Node.js · npm
npm install opentrust

const ot = new OpenTrust();
(await ot.lookup("9876543210")).reported

Both read OPENTRUST_API_KEY from the environment. See all libraries and integrations, including the Shopify and WooCommerce plugins on the way. Want a library for another language? Tell us.

Authentication

Send your key as a bearer token on every request. Keep it secret and revoke it from the dashboard if it leaks. Requests are limited to 120 per minute per key.

header
Authorization: Bearer ot_live_xxxxxxxxxxxxxxxxxxxxxxxx

POST /lookups

Check one number. Uses 1 check from your allowance. Any common format works: 98765 43210, 09876543210 or +919876543210.

curl -X POST https://opentrust.in/api/v1/lookups \
  -H "Authorization: Bearer $OPENTRUST_KEY" \
  -d phone=9876543210
const res = await fetch("https://opentrust.in/api/v1/lookups", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.OPENTRUST_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ phone: "9876543210" }),
});
const result = await res.json();
import os, requests

res = requests.post(
    "https://opentrust.in/api/v1/lookups",
    headers={"Authorization": f"Bearer {os.environ['OPENTRUST_KEY']}"},
    json={"phone": "9876543210"},
)
result = res.json()
$ch = curl_init("https://opentrust.in/api/v1/lookups");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("OPENTRUST_KEY"),
                         "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => json_encode(["phone" => "9876543210"]),
  CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
require "net/http"
require "json"

uri = URI("https://opentrust.in/api/v1/lookups")
req = Net::HTTP::Post.new(uri, "Authorization" => "Bearer #{ENV['OPENTRUST_KEY']}",
                               "Content-Type" => "application/json")
req.body = { phone: "9876543210" }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
result = JSON.parse(res.body)

Response 200

response.json
{
  "phone_last4": "3210",
  "reported": true,
  "report_count": 1,
  "reports": [
    {
      "reason_code": "cod_refusal",
      "reason": "Refused a cash-on-delivery order",
      "notes": "Refused 3 COD orders",
      "reported_at": "2026-10-01",
      "reporter_verified": true
    }
  ],
  "notice": "Reports are unverified observations shared by individual merchants. …",
  "checks_remaining": 99999
}
  • reports: [] and report_count: 0 mean no merchant has reported the number.
  • You never get the full number back, only phone_last4, and never who reported.
  • notice is included in every response. Please keep it in front of anyone who sees a result.

POST /lookups/batch

Check up to 100 numbers. Uses one check per number, all or nothing: if you don't have enough checks, none are used and you get a 402.

curl
curl -X POST https://opentrust.in/api/v1/lookups/batch \
  -H "Authorization: Bearer $OPENTRUST_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phones": ["9876543210", "9000000001"]}'

Response 200

response.json
{
  "results": [
    {
      "phone_last4": "3210",
      "reported": true,
      "report_count": 1,
      "reports": [
        "…"
      ]
    },
    {
      "phone_last4": "0001",
      "reported": false,
      "report_count": 0,
      "reports": [

      ]
    }
  ],
  "notice": "…",
  "checks_remaining": 99998
}

POST /reports

Share an experience with a number. Optional, and it doesn't change your allowance. Only share what your own business directly experienced, as plain facts.

curl
curl -X POST https://opentrust.in/api/v1/reports \
  -H "Authorization: Bearer $OPENTRUST_KEY" \
  -d phone=9876543210 \
  -d reason_code=cod_refusal \
  -d "notes=Refused 3 COD orders in March"

notes is optional, up to 500 characters. No names, accusations, emails, links or phone numbers. Each merchant can share one report per number.

Reason codes

Orders and payments

cod_refusal
Refused a cash-on-delivery order
fake_order
Placed an order that appeared fake
return_abuse
Repeated return or refund abuse
chargeback
Disputed a payment (chargeback)
fake_payment_proof
Shared payment proof that didn't check out

Impersonation and phone calls

otp_fraud
Asked someone for an OTP
bank_impersonation
Posed as a bank or financial institution
merchant_impersonation
Posed as our business or support
phishing_link
Sent a suspicious payment or login link
kyc_scam
Posed as a KYC or verification agent
refund_scam
Made a suspicious refund request

Other

identity_fraud
Used someone else's identity details
other
Other

Response 201

response.json
{
  "id": 42,
  "phone_last4": "3210",
  "status": "recorded"
}

GET /me

See your checks. Free to call.

response.json
{
  "merchant": "Your Shop",
  "checks_remaining": 99998,
  "reports_submitted": 3
}

Running low? Write to [email protected] and we'll set a generous limit.

Errors

Every error has the same shape:

error.json
{
  "error": {
    "code": "no_checks_remaining",
    "message": "You have used all your checks. …"
  }
}
401invalid_api_keyMissing or invalid API key
402no_checks_remainingNo checks left. Write to us and we'll raise your limit
403merchant_not_approvedAccount isn't approved or is suspended
409duplicate_reportYou already shared this number
422invalid_phone / invalid_reportInvalid number, reason code or note
429rate_limitedOver 120 requests per minute

Using results responsibly

Reports are unverified observations shared by individual merchants. They are not a finding that anyone committed fraud. Use them as one input among others, not as the sole reason to refuse a customer.

  • Have a person review any decision that materially affects a customer.
  • Don't tell customers that OpenTrust is the reason for a decision.
  • Don't resell, republish or bulk-export results. See the Terms.
opentrust-intro.mp4