Home/API Docs

API Documentation

Everything you need to integrate BillionCore BIN lookup into your application — from authentication to response fields.

Introduction

The BillionCore API is a high-performance REST API for BIN (Bank Identification Number) lookup. Given the first 6–8 digits of a payment card, it returns the issuing bank's country, card brand, card type, and transaction routing rules — in under 20 microseconds.

The engine is written in Go and operates entirely in-memory with zero database hops. All responses are JSON. No SDK is required — any HTTP client works.

Quick start

  1. 1. Register and copy your API key from the dashboard.
  2. 2. Send a GET request to https://engine.billioncore.tech/api/bin/lookup
  3. 3. Pass your key in the X-API-Key header.

Try it now — no signup

Copy this and run it. It uses a shared public demo key (rate-limited per IP), so you get a real 200 before you register — then grab your own free key for production.

# No signup — this shared public demo key works right now (rate-limited per IP)
curl "https://engine.billioncore.tech/api/bin/lookup?bin=453998&country=US&profile=affiliate&price=49.99" \
  -H "X-API-Key: bc_demo_BillionCoreStressTest2024"

Authentication

All requests require an API key. Keys are prefixed with bc_live_ and are generated instantly when you register.

Pass the key using either the X-API-Key header or as a Bearer token in the Authorization header.

GET /api/bin/lookup?bin=453998&country=US HTTP/1.1
Host: engine.billioncore.tech
X-API-Key: bc_live_yourkey

Keep your API key secret — treat it like a password. Never expose it in client-side code or public repositories.

Base URL

All API requests are made over HTTPS to the following base URL. HTTP is not supported.

Base URLhttps://engine.billioncore.tech

Endpoints

BillionCore exposes two main endpoints: a GET single-BIN lookup and a POST batch endpoint for up to 10,000 BINs in a single request. On the single-BIN endpoint, omit country to receive all configured country rules in one response.

BIN + Country lookup

GET

Returns a single routing rule for a specific BIN + country combination. This is the fastest path — one atomic load plus two map lookups, returning in under 1ms.

ParameterTypeRequiredDescription
binstringrequiredFirst 6–8 digits of the card number. The engine accepts both 6- and 8-digit BINs — if an 8-digit BIN is not yet in the dataset, it automatically falls back to the 6-digit prefix.
countrystringoptionalISO 3166-1 alpha-2 code (e.g. US, GB)
profilestringoptionalCustomer lens — retail (fraud/approval: approve·review·decline) or affiliate (traffic/rebill: force·keep·avoid). Omit for raw rules/action. When set, adds the analytics block (see Decision analytics).
verticalstringoptionalTraffic vertical that tunes the LTV horizon and chargeback cost: nutra, gambling, dating, vod, ecom, crypto. Requires profile.
pricefloatoptionalYour rebill price in USD. Unlocks LTV in analytics.economics. Falls back to the BIN's configured rebill price when omitted.
payoutfloatoptionalYour acquisition cost (CPA) in USD. Unlocks ROI, EV and breakeven in analytics.economics.

Request

curl "https://engine.billioncore.tech/api/bin/lookup?bin=453998&country=US" \
  -H "X-API-Key: bc_live_yourkey"

# Add a decision lens + economics — risk, recommendation and projected LTV/ROI
curl "https://engine.billioncore.tech/api/bin/lookup?bin=453998&country=US&profile=affiliate&vertical=nutra&price=49.99&payout=20" \
  -H "X-API-Key: bc_live_yourkey"

Response

{
  "success": true,
  "data": {
    "bin":           "411111",
    "country":       "US",
    "action":        "FORCE",
    "trial_price":   3.00,
    "trial_period":  3,
    "rebill_price":  39.74,
    "rebill_period": 30,
    "x_sell_status": "FORCE",
    "configured":    true,
    "bin_performance": {
      "gross_profit": 68.2,
      "lead_u":       72.5,
      "first_rebill": 88.0,
      "rebill":       41.3,
      "tc40_safe":    1.2,
      "cb":           0.8,
      "refund":       1.1,
      "risk_score":   8
    },
    "issuer": {
      "card_brand":  "visa",
      "card_type":   "credit",
      "issuer_name": "Jpmorgan Chase Bank, N.a.",
      "country":     "us"
    }
  },
  "timestamp": "2026-06-02T20:00:00Z"
}

BIN-only lookup (all country rules)

GET

Omit the country parameter to receive all configured routing rules for a given BIN in a single response. Useful for admin tooling, data exploration, or when you want to see all market configurations at once.

ParameterTypeRequiredDescription
binstringrequiredFirst 6–8 digits of the card number

Request

curl "https://engine.billioncore.tech/api/bin/lookup?bin=453998" \
  -H "X-API-Key: bc_live_yourkey"

Response

{
  "success": true,
  "data": {
    "bin": "411111",
    "rules": {
      "US": {
        "action":        "FORCE",
        "trial_price":   3.00,
        "trial_period":  3,
        "rebill_price":  39.74,
        "rebill_period": 30,
        "x_sell_status": "FORCE"
      },
      "GB": {
        "action":        "DISABLE",
        "trial_price":   0,
        "trial_period":  0,
        "rebill_price":  0,
        "rebill_period": 0,
        "x_sell_status": "DISABLE"
      }
    },
    "bin_performance": {
      "gross_profit": 68.2,
      "lead_u":       72.5,
      "first_rebill": 88.0,
      "rebill":       41.3,
      "tc40_safe":    1.2,
      "cb":           0.8,
      "refund":       1.1,
      "risk_score":   8
    },
    "issuer": {
      "card_brand":  "visa",
      "card_type":   "credit",
      "issuer_name": "Jpmorgan Chase Bank, N.a.",
      "country":     "us"
    }
  },
  "timestamp": "2026-06-02T20:00:00Z"
}

Batch lookup

POST

Process up to 10,000 BINs in a single request. Each item in the batch counts as one API call toward your plan usage. Country is optional per item — with a country code the response contains a single routing rule; without a country code it returns all configured country rules for that BIN.

10,000 BINs processed in under 300ms. Each item in the batch counts as one API call toward your plan usage.

FieldTypeRequiredDescription
lookupsarrayrequiredArray of lookup items (max 10,000)
lookups[].binstringrequiredFirst 6–8 digits of the card
lookups[].countrystringoptionalISO 3166-1 alpha-2. Omit for all-country rules
lookups[].weightfloatoptionalTraffic volume for this BIN. Weights the portfolio roll-up so high-volume BINs dominate the blended figures. Defaults to 1.

Add ?profile=affiliate (with optional vertical/price/payout) to the batch URL and the response gains per-item analytics plus a top-level portfolio summary — see Decision analytics.

Request

# Plain batch — routing rules only
curl "https://engine.billioncore.tech/api/bin/batch" \
  -X POST \
  -H "X-API-Key: bc_live_yourkey" \
  -H "Content-Type: application/json" \
  -d '{"lookups":[{"bin":"453998","country":"US"},{"bin":"411111","country":"GB"},{"bin":"516793"}]}'

# Affiliate analytics + portfolio — add ?profile (and optional vertical/price/
# payout). Optional per-item "weight" = traffic volume for the portfolio roll-up.
curl "https://engine.billioncore.tech/api/bin/batch?profile=affiliate&vertical=nutra&price=49.99" \
  -X POST \
  -H "X-API-Key: bc_live_yourkey" \
  -H "Content-Type: application/json" \
  -d '{"lookups":[{"bin":"453998","country":"US","weight":5},{"bin":"516793","country":"US","weight":2}]}'

Response

{
  "success": true,
  "count": 3,
  "results": [
    {
      "bin": "679196",
      "country": "NL",
      "action": "FORCE",
      "trial_price": 3,
      "trial_period": 3,
      "rebill_price": 90,
      "rebill_period": 30,
      "x_sell_status": "FORCE",
      "issuer": {
        "card_brand": "maestro",
        "card_type": "debit"
      },
      "configured": true
    },
    {
      "bin": "679835",
      "country": "ES",
      "action": "DISABLE",
      "trial_price": 3,
      "trial_period": 3,
      "rebill_price": 33,
      "rebill_period": 14,
      "x_sell_status": "DISABLE",
      "issuer": {
        "card_brand": "maestro",
        "card_type": "debit"
      },
      "configured": true
    },
    {
      "bin": "453998",
      "country": "US",
      "action": "FORCE",
      "x_sell_status": "FORCE",
      "bin_performance": {
        "gross_profit": 51.6,
        "lead_u": 45.1,
        "first_rebill": 85,
        "rebill": 38.6,
        "tc40_safe": 3.82,
        "refund": 2.78,
        "risk_score": 14
      },
      "issuer": {
        "card_brand": "visa",
        "card_type": "credit",
        "issuer_name": "Cartasi S.p.a.",
        "country": "it"
      },
      "configured": false,
      "inference": {
        "score": 100,
        "signals": [
          { "key": "card_type",         "value": "credit", "impact": 20, "label": "Credit card — best for recurring billing" },
          { "key": "risk_score",        "value": 14,       "impact": 20, "label": "Clean BIN — low fraud history" },
          { "key": "first_rebill_rate", "value": 85,       "impact": 15, "label": "Strong first rebill rate" },
          { "key": "gross_profit",      "value": 51.6,     "impact": 10, "label": "Profitable BIN historically" }
        ]
      }
    }
  ],
  "timestamp": "2026-06-03T19:48:23Z"
}

Response fields

All successful responses follow the shape { success: true, data: {...} }. The fields inside data are described below.

Common (both endpoints)

FieldTypeDescription
binstringThe BIN prefix (6–8 digits)
issuerobject?Card issuer metadata — present when known
issuer.card_brandstring?Payment network: visa, mastercard, amex, discover…
issuer.card_typestring?credit, debit, prepaid, or charge
issuer.issuer_namestring?Issuing bank name (best-effort, may lag rebrands)
issuer.countrystring?ISO 3166-1 alpha-2 country of the issuing bank
bin_performanceobject?Historical performance metrics — present when available
bin_performance.gross_profitfloatAverage gross profit % for this BIN
bin_performance.lead_ufloatLead conversion rate %
bin_performance.first_rebillfloatFirst rebill success rate %
bin_performance.rebillfloatOngoing rebill success rate %
bin_performance.tc40_safefloatTC40/SAFE fraud indicator %
bin_performance.cbfloatChargeback rate %
bin_performance.refundfloatRefund rate %
bin_performance.risk_scoreintPre-computed risk score 0–100 (0 = clean, 100 = critical)

BIN + Country response

FieldTypeDescription
countrystringISO 3166-1 alpha-2 country code
actionstringFORCE | DISABLE | INHERIT — routing decision for this card
trial_pricefloatTrial period charge in USD
trial_periodintTrial length in days
rebill_pricefloatRecurring charge in USD
rebill_periodintRecurring interval in days
x_sell_statusstringCross-sell eligibility flag
configuredbooltrue if action came from an explicit rule; false if derived by smart inference
inferenceobject?Present only when configured=false — explains how the action was derived
inference.scoreint0–100 confidence score (≥65→FORCE, 35–64→INHERIT, <35→DISABLE)
inference.signalsarrayContributing factors with key, value, impact (pts), and human-readable label
recommendationobject?Present only when profile is set. Segment-specific decision.

Recommendation object

FieldTypeDescription
profilestringretail | affiliate
decisionstringretail: approve·review·decline · affiliate: force·keep·avoid
reasonsarrayhuman-readable factors behind the decision

Action values

ValueMeaning
FORCEProcess this card — use the defined trial/rebill pricing
DISABLEBlock this card in this country — do not process
INHERITNo country-specific rule — fall back to the global default

Decision analytics

profile

Add ?profile=retail or ?profile=affiliate and the response gains an analytics block: projected rebill economics, peer-segment benchmarks, a confidence rating, and routing hints. The universal response is unchanged when no profile is requested. On the batch endpoint a portfolio-level portfolio summary is added alongside the per-item analytics.

Economics are modeled estimates, not settled results. When a BIN has no measured history the figures are inferred from its peer segment and estimated is true; always read confidence alongside the numbers. approval_likelihood is a modeled planning figure, not a measured authorisation rate.

analytics object

FieldTypeDescription
profilestringretail | affiliate
estimatedbooltrue when performance came from a peer-segment prior, not this BIN
confidenceobjectHow much to trust the figures (see below)
economicsobjectProjected money + profit grade (see below)
benchmarksarrayPercentile rank of each metric vs the peer segment
routingobject?Operational hints — present when relevant

economics object

FieldTypeDescription
verticalstringResolved vertical (default unless ?vertical= given)
assumed_rebill_pricefloatPrice used for $ projections (from ?price= or the BIN rule)
projected_rebillsfloatExpected successful rebills per approved customer over the vertical horizon
approval_likelihoodfloatModeled 0–1 authorisation probability (planning estimate, not measured)
profit_gradestringA–F grade from the rate signals (price-independent)
ltv_per_approvedfloat?Net projected $ over the rebill chain — needs a price
roi_pctfloat?Return on the payout — needs ?payout=
ev_per_approvedfloat?ltv − payout — needs ?payout=
breakeven_payoutfloat?Max CPA to break even (= ltv) — needs a price

confidence object

FieldDescription
levelhigh | medium | low
basisbin (own data) | segment_prior | global
segmentPeer segment used, e.g. visa/credit/US
samplesPeer BINs backing an estimate

benchmarks & routing

FieldDescription
benchmarks[].metricfirst_rebill, rebill, gross_profit, cb, refund, risk
benchmarks[].percentile0–100 vs peer segment — higher is always better
routing.recommend_3dsStep-up authentication advised
routing.retry_strategye.g. retry_after_payday for debit
routing.notePlain-language routing tip

portfolio object (batch only)

FieldTypeDescription
bins / bins_with_dataintTotal BINs and how many could be scored
weighted_first_rebillfloatVolume-weighted first-rebill % across the batch
weighted_risk_scorefloatVolume-weighted average risk score
blended_chargebackfloatVolume-weighted chargeback %
avg_projected_ltvfloatAverage projected LTV per approved customer
chargeback_ceilingfloatScheme monitoring threshold % (Visa VAMP ≈ 0.9)
ceiling_used_pctfloatHow much of the ceiling the blended chargeback uses
compliance_statusstringhealthy | watch | critical
top_issuer_countrystring?Most-concentrated issuer country
concentration_pctfloatShare of volume in the top issuer country
best / worstarrayRanked BINs to keep/scale or review/cut

Portfolio response (batch with ?profile=affiliate)

"portfolio": {
  "bins": 3,
  "bins_with_data": 3,
  "weighted_first_rebill": 72.42,
  "weighted_risk_score": 18.1,
  "blended_chargeback": 0.1,
  "blended_refund": 8.34,
  "avg_projected_ltv": 48.73,
  "chargeback_ceiling": 0.9,
  "ceiling_used_pct": 11.11,
  "compliance_status": "healthy",
  "top_issuer_country": "IT",
  "concentration_pct": 50,
  "best":  [ { "bin": "453998", "grade": "B", "risk_score": 14 } ],
  "worst": [ { "bin": "411111", "grade": "F", "risk_score": 33 } ]
}

Error codes

Errors always have success: false and a human-readable error string. The HTTP status code mirrors the error type.

StatusMeaning
401Missing or invalid API key
400Missing required bin parameter
500Internal server error — contact support

Error responses

{
  "success": false,
  "error": "Unauthorized"
}

Code examples

Full working examples for the most common languages and frameworks. All examples use the BIN + Country endpoint — omit &country=US to get all country rules instead.

curl

The fastest way to test your key. Works in any terminal.

# Single country
curl "https://engine.billioncore.tech/api/bin/lookup?bin=453998&country=US" \
  -H "X-API-Key: bc_live_yourkey"

# All country rules
curl "https://engine.billioncore.tech/api/bin/lookup?bin=453998" \
  -H "X-API-Key: bc_live_yourkey"

PHP (vanilla)

Uses cURL extension, available in every PHP installation.

<?php

function billioncore_lookup(string $bin, string $country = ''): array
{
    $url = 'https://engine.billioncore.tech/api/bin/lookup?bin=' . urlencode($bin);
    if ($country !== '') {
        $url .= '&country=' . urlencode($country);
    }

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => [
            'X-API-Key: ' . $_ENV['BILLIONCORE_API_KEY'],
            'Accept: application/json',
        ],
        CURLOPT_TIMEOUT        => 5,
    ]);
    $body = curl_exec($ch);
    curl_close($ch);

    return json_decode($body, true);
}

// Usage
$result = billioncore_lookup('453998', 'US');

if ($result['success']) {
    $data = $result['data'];
    echo "Action: " . $data['action'] . PHP_EOL;          // "FORCE"
    echo "Trial:  $" . $data['trial_price'] . " / " . $data['trial_period'] . " days" . PHP_EOL;
    echo "Rebill: $" . $data['rebill_price'] . " / " . $data['rebill_period'] . " days" . PHP_EOL;
    echo "Brand:  " . ($data['issuer']['card_brand'] ?? 'unknown') . PHP_EOL;
    echo "Bank:   " . ($data['issuer']['issuer_name'] ?? 'unknown') . PHP_EOL;
    echo "Risk:   " . ($data['bin_performance']['risk_score'] ?? 'n/a') . "/100" . PHP_EOL;
}

Laravel

Recommended pattern: store the key in config, use the HTTP facade.

<?php

return [
    // ...

    'billioncore' => [
        'key'      => env('BILLIONCORE_API_KEY'),
        'base_url' => env('BILLIONCORE_BASE_URL', 'https://engine.billioncore.tech'),
    ],
];

JavaScript / Node.js

Works in the browser and Node.js. Uses the native fetch API.

const BILLIONCORE_KEY  = process.env.BILLIONCORE_API_KEY;
const BILLIONCORE_BASE = 'https://engine.billioncore.tech';

async function lookupBin(bin, country) {
  const url = new URL('/api/bin/lookup', BILLIONCORE_BASE);
  url.searchParams.set('bin', bin);
  if (country) url.searchParams.set('country', country);

  const res = await fetch(url.toString(), {
    headers: { 'X-API-Key': BILLIONCORE_KEY },
  });

  if (!res.ok) {
    const err = await res.json();
    throw new Error(err.error ?? 'BillionCore error');
  }

  return res.json().then(r => r.data);
}

// Usage
const data = await lookupBin('453998', 'US');

if (data.action === 'FORCE') {
  console.log('Trial: $' + data.trial_price + ' / ' + data.trial_period + ' days');
  console.log('Brand:', data.issuer?.card_brand);    // "visa"
  console.log('Risk: ', data.bin_performance?.risk_score); // 8
}

Python

Uses the requests library. Compatible with Django, FastAPI, Flask.

import os
import requests
from typing import Optional

BILLIONCORE_KEY  = os.environ["BILLIONCORE_API_KEY"]
BILLIONCORE_BASE = "https://engine.billioncore.tech"


def lookup_bin(bin: str, country: Optional[str] = None) -> dict:
    params = {"bin": bin}
    if country:
        params["country"] = country

    resp = requests.get(
        f"{BILLIONCORE_BASE}/api/bin/lookup",
        params=params,
        headers={"X-API-Key": BILLIONCORE_KEY},
        timeout=5,
    )
    resp.raise_for_status()
    return resp.json()["data"]


data = lookup_bin("453998", "US")

if data["action"] == "FORCE":
    print(f"Trial:  {data['trial_price']{'}'} / {'{'}data['trial_period']{'}'} days")
    print(f"Brand:  {'{'}data.get('issuer', {'{}'}).get('card_brand', 'n/a'){'}'}")
    print(f"Risk:   {'{'}data.get('bin_performance', {'{}'}).get('risk_score', 'n/a'){'}'}/100")

Go

Zero external dependencies — uses the standard library only.

package billioncore

import (
    "context"
    "encoding/json"
    "fmt"
    "net/http"
    "net/url"
    "os"
    "time"
)

type Client struct {
    apiKey  string
    baseURL string
    http    *http.Client
}

type LookupData struct {
    Bin          string          `json:"bin"`
    Country      string           `json:"country,omitempty"`
    Action       string           `json:"action"`
    TrialPrice   float64          `json:"trial_price"`
    TrialPeriod  int              `json:"trial_period"`
    RebillPrice  float64          `json:"rebill_price"`
    RebillPeriod int              `json:"rebill_period"`
    XSellStatus  string           `json:"x_sell_status"`
    Performance  *BinPerformance  `json:"bin_performance,omitempty"`
    Issuer       *Issuer          `json:"issuer,omitempty"`
    Rules        map[string]Rule  `json:"rules,omitempty"`
}

type Rule struct {
    Action      string  `json:"action"`
    TrialPrice  float64 `json:"trial_price"`
    RebillPrice float64 `json:"rebill_price"`
}

type BinPerformance struct {
    GrossProfit float64 `json:"gross_profit"`
    RiskScore   int     `json:"risk_score"`
}

type Issuer struct {
    CardBrand  string `json:"card_brand"`
    CardType   string `json:"card_type"`
    IssuerName string `json:"issuer_name"`
    Country    string `json:"country"`
}

func NewClient() *Client {
    return &Client{
        apiKey:  os.Getenv("BILLIONCORE_API_KEY"),
        baseURL: "https://engine.billioncore.tech",
        http:    &http.Client{Timeout: 5 * time.Second},
    }
}

func (c *Client) Lookup(ctx context.Context, bin, country string) (*LookupData, error) {
    u, _ := url.Parse(c.baseURL + "/api/bin/lookup")
    q := u.Query()
    q.Set("bin", bin)
    if country != "" {
        q.Set("country", country)
    }
    u.RawQuery = q.Encode()

    req, _ := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
    req.Header.Set("X-API-Key", c.apiKey)

    resp, err := c.http.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        var errResp struct{ Error string `json:"error"` }
        json.NewDecoder(resp.Body).Decode(&errResp)
        return nil, fmt.Errorf("billioncore: %s", errResp.Error)
    }

    var result struct {
        Data LookupData `json:"data"`
    }
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return nil, err
    }
    return &result.Data, nil
}

Ready to integrate?

Get your API key in seconds — no credit card required.

Start free 30-day trial