Home Pricing Dashboard Get API Key

DevRoute SDK

One script tag. Instant device intelligence — eSIM support, fraud signals, network type, and smart conversion routing for every visitor.

DevRoute works entirely client-side. You add a <script> tag, call DevRoute.init(), and receive a structured result object with everything you need to route, personalize, or protect your users. No build step. No dependencies. No npm.

Just a script tag. Works on any website — vanilla HTML, React, Vue, WordPress, Webflow. If it runs JavaScript in a browser, DevRoute works.

Quick Start

Three steps to get your first device result.

1
Get your API key

Sign up at devroute.app/register. Your key is available immediately on the dashboard.

2
Add the script tag

Paste this in the <head> or just before </body> of your page.

3
Call DevRoute.init()

Pass your API key and an onResult callback. That's it.

html
<!-- Step 2: Add the SDK -->
<script src="https://www.devroute.app/sdk/v3/devroute.min.js"></script>

<!-- Step 3: Initialize -->
<script>
  DevRoute.init({
    apiKey: 'esim_live_YOUR_API_KEY',
    onResult: function(result) {
      console.log('Device:', result.device.brand, result.device.model);
      console.log('eSIM supported:', result.esim?.supported);
    }
  });
</script>

Installation

CDN (recommended)

Always points to the latest v3 release. Cached globally via Cloudflare CDN.

html
<script src="https://www.devroute.app/sdk/v3/devroute.min.js"></script>

Pinned version

Use a specific version if you need reproducible builds.

html
<script src="https://www.devroute.app/sdk/v3.0.0/devroute.min.js"></script>

The SDK is a single file with zero dependencies and no external requests beyond the DevRoute API. It works offline (returns cached data from sessionStorage on repeat calls within the same browser tab).

DevRoute.init(options)

The single entry point. Call it once per page load — usually right after the script tag. Results are cached in sessionStorage so repeat calls within the same tab return instantly without an extra API request.

javascript
DevRoute.init({
  // Required
  apiKey: 'esim_live_YOUR_API_KEY',

  // Called with the result object when detection succeeds
  onResult: function(result) {
    // result contains device, eSIM, network, and risk data
  },

  // Called if the API request fails (optional)
  onError: function(err) {
    console.warn('DevRoute error:', err.message);
  }
});

Options

Option Type Required Description
apiKey string Required Your DevRoute API key. Get it from the dashboard. Format: esim_live_...
onResult function Optional Callback invoked with the result object on success. Also called immediately with cached data if available.
onError function Optional Callback invoked if the API request fails. Receives an Error object.
apiEndpoint string Optional Override the API endpoint. Defaults to the DevRoute edge worker at https://api.devroute.app/detect. Only change this if instructed by support.
mode string Optional 'full' (default) or 'light'. Use 'light' to get a reduced result object optimized for quick eSIM + routing decisions. See Light mode.
onRule function Optional Callback invoked when custom business rules match. Receives an array of matched rules: [{ label, action, type, value }]. See Rules.

Response Object

The result object passed to onResult. The response is structured in grouped blocks. Available fields depend on your plan — blocks from higher plans are null on lower plans.

javascript — full response shape (v3)
{
  // ── Device — Free+ ──────────────────────────────────────────────────
  device: {
    id:               "sha256_device_hash",  // unique device fingerprint
    brand:            "Samsung",
    model:            "Galaxy S24",
    type:             "Galaxy S24 Ultra 5G",
    confidence:       0.92,
    detectionMethod:  "server-index-lookup",
    os: {
      name:    "Android",
      version: "14"
    },
    screenResolution: "1080x2340",
    pixelRatio:       3,
    timezone:         "America/New_York",
    language:         "en-US",
    family:           "Galaxy S24 Series",
    hash:             "sha256..."
  },

  // ── eSIM — Starter+ ─────────────────────────────────────────────────
  esim: {
    supported:         true,
    dualEsim:          false,
    conversionStrategy: "guided_install",
    recommendedFlow:    "step_by_step",
    osReady:           true,
    minOs:             "9.0",
    transferSupported:  false
  },

  // ── Network — Growth+ ───────────────────────────────────────────────
  network: {
    type:         "4g",
    ip:           "203.0.113.42",
    isp:          "Comcast Cable",
    vpn:          false,
    webrtcLeak:   false,
    asn:          7922,
    httpProtocol: "HTTP/2",
    tlsVersion:   "TLSv1.3",
    velocity: {
      flagged: false,
      count:   0
    }
  },

  // ── Hardware — Growth+ ──────────────────────────────────────────────
  hardware: {
    gpu:     "Adreno 750",
    ram:     8,
    cores:   8
  },

  // ── Security — Enterprise+ ──────────────────────────────────────────
  security: {
    privateMode:          null,
    emulator:             false,
    bot:                  false,
    botSubtype:           null,
    webrtcRealIp:         null,
    riskScore:            8,
    threatScore:          0,
    conflicts:            [],
    identityInconsistent: false,
    consistency: {
      score:   1.0,
      reasons: []
    }
  },

  // ── Geolocation — Enterprise+ ───────────────────────────────────────
  geolocation: {
    country:            "US",
    city:               "New York",
    region:             "New York",
    continent:          "NA",
    postalCode:         "10001",
    isEUCountry:        false,
    latitude:           40.71,
    longitude:          -74.00,
    timezoneMismatch:   false
  },

  // ── Intelligence — Starter+ ─────────────────────────────────────────
  intelligence: {
    decisions: { // 5 layers — depth varies by plan },
    profile:     { // user segment — Growth+ },
    scores:      { // risk/conversion/experience — Growth+ },
    narrative:   { // headlines and recommendations }
  },

  // ── Rules — Starter+ ────────────────────────────────────────────────
  rules: [
    {
      name:      "US Premium Flow",
      label:     "us_premium",
      type:      "country",
      value:     "US",
      action:    "allow",
      priority:  10,
      tags:      ["geo"],
      matchedOn: ["country"]
    }
  ],

  // ── Access — Enterprise+ ────────────────────────────────────────────
  access: {
    outcome:    "allow",
    source:     "system",
    reason:     "low_fraud_risk",
    confidence: 0.85
  }
}

Field reference

Field Type Description Plan
device.idstringSHA-256 device fingerprint (stable across sessions)Free
device.brandstringDevice manufacturerFree
device.modelstringDevice model nameFree
device.typestringFull device type stringFree
device.confidencenumberDetection confidence 0.0–1.0Free
device.detectionMethodstringHow the device was identifiedFree
device.osobject{ name, version } — OS detectedFree
device.familystringDevice family / product lineFree
device.hashstringStable device fingerprint for cross-session trackingFree
esim.supportedbooleanWhether the device supports eSIMStarter
esim.dualEsimbooleanTwo concurrent eSIMs supportedStarter
esim.conversionStrategystringRecommended install strategyStarter
esim.recommendedFlowstringRecommended UI flowStarter
esim.osReadybooleanOS version supports eSIM installationStarter
esim.minOsstringMinimum OS version for eSIMStarter
esim.transferSupportedbooleaneSIM device-to-device transferStarter
intelligence.decisions.*objectFive decisions as { value, reason }Starter
intelligence.narrativeobjectHeadlines and recommendationsStarter
rulesarrayMatched custom rules — fires onRule callbackStarter
intelligence.profileobjectUser segment, confidence, signalsGrowth
intelligence.authenticityobjectAuthenticity score (0–100) + verdictGrowth
intelligence.scoresobjectrisk / conversion / experience (0–100)Growth
network.typestring"2g" / "3g" / "4g" / "5g" / "wifi"Growth
network.ipstringClient IP addressGrowth
network.ispstringISP name (from Cloudflare edge)Growth
network.vpnbooleanVPN or datacenter connectionGrowth
network.webrtcLeakbooleanWebRTC leaked real IPGrowth
network.asnnumberAutonomous system numberGrowth
network.httpProtocolstringHTTP version ("HTTP/2" / "HTTP/3")Growth
network.tlsVersionstringTLS versionGrowth
network.velocityobject{ flagged, count } — request velocity (Growth+)Growth
hardware.gpustringGPU renderer stringGrowth
hardware.ramnumberDevice RAM in GBGrowth
hardware.coresnumberCPU core countGrowth
security.emulatorbooleanEmulator or automation toolEnterprise
security.botbooleanHeadless browser or scraperEnterprise
security.riskScorenumberFraud risk score 0–100Enterprise
security.privateModebooleanBrowser private / incognito modeEnterprise
security.webrtcRealIpstringReal IP leaked behind VPNEnterprise
security.threatScorenumberIP threat score from Proxycheck.ioEnterprise
security.conflictsarrayCross-signal contradictionsEnterprise
security.consistencyobject{ score, reasons } — identity consistencyEnterprise
geolocation.countrystringISO 3166-1 alpha-2Enterprise
geolocation.citystringCity nameEnterprise
geolocation.regionstringRegion / stateEnterprise
geolocation.latitudenumberGPS latitude from Cloudflare edgeEnterprise
geolocation.longitudenumberGPS longitudeEnterprise
geolocation.isEUCountrybooleanTrue if EU countryEnterprise
geolocation.timezoneMismatchbooleanBrowser TZ ≠ IP TZ — VPN signalEnterprise
access.outcomestring"allow" / "block" / "challenge"Enterprise
access.reasonstringReason for access decisionEnterprise
access.confidencenumberConfidence in access decisionEnterprise

Conversion strategies

The esim.conversionStrategy field tells you how to best route the user. Use it to show the right flow without asking the user to self-identify their device.

conversionStrategyrecommendedFlowMeaningRecommended action
"direct_install""auto_install"iOS 16+ or Google Pixel — carrier tap-through availableShow "Activate eSIM" button; deep-link to carrier activation URL
"guided_install""step_by_step"Samsung or Android 12+ — OS-native eSIM wizard availableOpen step-by-step modal linking to Settings > Mobile > Add eSIM
"qr_install""scan_qr"eSIM supported, no native deep-link flowDisplay QR code with scan instructions
"manual_install""manual_setup"Low confidence detection, cannot verify deviceShow activation code entry form as fallback
"unsupported_device""show_unsupported"Device confirmed as eSIM-incapableShow upgrade prompt or physical SIM flow

Detection methods

The detectionMethod field indicates how the device was identified, which reflects detection confidence:

ValueConfidenceDescription
"server-iphone-direct"HighMatched via screen resolution + DPR matrix (iPhone/iPad)
"server-multi-signal"HighMatched via UA + resolution + DPR + OS + touch scoring
"server-index-lookup"MediumMatched via Android model code index (42,000+ codes)
"server-ua-extract"MediumExtracted from UA string with brand inference
"gpu_cpu_ram_inference"Low–MediumInferred from GPU + CPU family + RAM/screen signals

Light Mode

Starter Use mode: 'light' to get a minimal response object optimized for quick eSIM routing decisions without the full device intelligence payload.

javascript — light mode
DevRoute.init({
  apiKey: 'esim_live_YOUR_KEY',
  mode: 'light',           // ← minimal response
  onResult: function(result) {
    // result is a grouped object, no flat fields
    console.log(result.device?.brand);    // "Samsung"
    console.log(result.esim?.supported);  // true
    console.log(result.network?.type);    // "4g"
    console.log(result.rules);             // matched rules array
    console.log(result.access?.outcome);  // "allow" | "block" | "flag"
  }
});

Light mode structure

The response is grouped into nested objects — no flat fields. Each group is populated only for the plan level it belongs to:

KeyContentPlan
device{ id, brand, model, type }Free
esim{ supported, dualEsim, strategy, osReady }Starter
intelligence{ decisions, narrative }Starter
rules[{ label, action, type, value }]Starter
network{ type, vpn, isp }Growth
hardware{ gpu, ram, cores }Growth
geolocation{ country, city }Enterprise
security{ bot, emulator, riskScore }Enterprise
access{ outcome, reason, confidence }Enterprise

Cached results. Light mode results are also cached in sessionStorage. Subsequent calls in the same tab return instantly without an API request.

Rules — onRule Callback

Starter When a custom business rule matches on the server, the SDK fires the onRule callback with an array of all matched rules. If multiple rules match, you receive them all in priority order.

javascript — onRule callback
DevRoute.init({
  apiKey: 'esim_live_YOUR_KEY',
  onResult: function(result) {
    // handle device intelligence
  },
  onRule: function(rules) {
    // rules = [{ label, action, type, value }, ...]
    rules.forEach(function(rule) {
      if (rule.action === 'block') {
        showBlockedMessage(rule.label);
      } else if (rule.action === 'flag') {
        logSuspicious(rule.label, rule.type);
      } else if (rule.action === 'allow') {
        enablePremiumFlow(rule.value);
      }
    });
  }
});

Rule object fields

FieldTypeDescription
labelstringProgrammatic identifier (e.g. "us_premium", "eu_strict"). Use this for logic, not type.
actionstring"allow" | "block" | "flag"
typestringRule condition type — for logging/analytics
valuemixedThe value that triggered the rule (e.g. "US" for country match)

Convention: Use rule.label for programmatic logic and rule.type for analytics/debugging. Don't rely on rule.value type — it may be string, number, or boolean depending on the rule.

Helper Methods

Utilities you can call after DevRoute.init() has run:

javascript — helpers
// Get the last matched rule (null if none)
var rule = DevRoute.getRule();
// → { label: "us_premium", action: "allow", type: "country", value: "US" }

// Get the full cached result object
var cached = DevRoute.getLastResult();
// → full result object (with rules array, etc.)

// SDK version
console.log(DevRoute.version); // "3.0.0"
MethodReturnsDescription
DevRoute.getRule()object | nullLast matched rule from the current session, or null
DevRoute.getLastResult()object | nullFull cached result from sessionStorage
DevRoute.versionstringCurrent SDK semver ("3.0.0")

Intelligence Engine

Available on Starter and above. The engine runs five decision layers on every detection and returns structured outputs with a value and a human-readable reason.

Decisions — intelligence.decisions

Each field returns { value: string, reason: string }. Use value to drive logic and reason to display context or log decisions.

javascript
var d = result.intelligence.decisions;

        // Always use .value to drive your logic
        console.log(d.esim_flow.value);   // "auto_install"
        console.log(d.esim_flow.reason);  // "iOS 17 with confirmed eSIM — use Quick Transfer"

        console.log(d.friction.value);    // "none" | "soft" | "hard"
        console.log(d.security_gate.value); // "none" | "review" | "block"
        console.log(d.ui_mode.value);     // "streamlined" | "standard" | "cautious"
        console.log(d.priority.value);    // "high" | "medium" | "low"
DecisionValuesDescription
esim_flowauto_install / step_by_step / scan_qr / manual_setup / show_unsupportedWhich eSIM installation flow to trigger
frictionnone / soft / hardWhether to add verification steps (soft = captcha, hard = SMS OTP)
security_gatenone / review / blockWhether to allow, flag for review, or block the session
ui_modestreamlined / standard / cautiousHow much to simplify or guard your UI for this session
priorityhigh / medium / lowConversion priority — use for A/B testing and upsell targeting

Profile & scores — Growth

Growth plan adds user segment classification and three conversion scores:

javascript
var intel = result.intelligence;

// User segment
intel.profile.segment;     // "genuine_user" | "corporate_user" | "privacy_user"
                            // | "traveler" | "developer" | "fraudulent_actor"
                            // | "automated_actor" | "tor_user" | "unclassified"
intel.profile.confidence;  // 0.0–1.0 segment confidence
intel.profile.signals;    // ["esim_capable", "residential_isp", ...]

// Authenticity
intel.authenticity.score;   // 0–100 (higher = more authentic)
intel.authenticity.verdict; // "authentic" | "suspicious" | "likely_bot"

// Scores (0–100)
intel.scores.risk;        // fraud risk (lower = safer)
intel.scores.conversion;  // likelihood to convert (higher = better)
intel.scores.experience;  // UX quality score — use to gate premium features

Error Handling

If the API call fails — network timeout, invalid API key, or plan limit reached — the onError callback is called. The SDK never throws; all errors are caught internally.

javascript
DevRoute.init({
  apiKey: 'esim_live_YOUR_KEY',
  onResult: function(result) {
    // happy path
  },
  onError: function(err) {
    // err.message — human-readable error
    // Common: "HTTP 401" (bad key), "HTTP 429" (limit reached), network errors
    console.warn('[DevRoute]', err.message);
  }
});
HTTP StatusMeaningWhat to do
401Invalid API keyCheck your key in the dashboard. Ensure the request comes from a whitelisted domain.
429Monthly detection limit reachedUpgrade your plan or wait for the next billing cycle.
500Detection failedRare. Contact support if it persists.

Domain locking. API keys can be restricted to specific domains. If you see a 401 on a new domain, add it to the allowed domains list in API Keys settings.

Example — eSIM Routing

Show the right onboarding flow based on real device eSIM support.

javascript — starter plan
DevRoute.init({
  apiKey: 'esim_live_YOUR_KEY',
  onResult: function(result) {
    var flow = result.esim.conversionStrategy;

    if (flow === 'direct_install') {
      // iOS 16+ / Pixel — tap-through carrier activation, no QR needed
      showActivateButton(carrierDeepLinkUrl);

    } else if (flow === 'guided_install') {
      // Samsung / Android 12+ — OS-native Settings wizard
      showGuidedModal(result.brand, result.OS.version);

    } else if (flow === 'qr_install') {
      // eSIM supported, show QR code for profile download
      showQRCode();

    } else if (flow === 'manual_install') {
      // Low-confidence detection — show activation code entry
      showActivationCodeForm();

    } else if (flow === 'unsupported_device') {
      // Device can't use eSIM — offer physical SIM or upgrade
      showPhysicalSimFallback();
    }

    // Optional: use intelligence decisions for UX fine-tuning
    var d = result.intelligence?.decisions;
    if (d?.ui_mode?.value === 'streamlined') collapseSecondaryOptions();
    if (d?.priority?.value === 'high') showPremiumPlanBanner();
  }
});

Example — Fraud Detection

Block or flag sessions with high risk signals before checkout. Use intelligence.decisions (Starter+) for decision logic, and risk_score / bot (Enterprise+) for numerical thresholds.

javascript — starter plan (decisions)
DevRoute.init({
  apiKey: 'esim_live_YOUR_KEY',
  onResult: function(result) {
    var gate     = result.intelligence?.decisions?.security_gate?.value;
    var friction = result.intelligence?.decisions?.friction?.value;

    if (gate === 'block') {
      blockSession();          // high-confidence fraud
    } else if (gate === 'review' || friction === 'hard') {
      showSmsVerification();   // suspicious — step-up auth
    } else if (friction === 'soft') {
      showCaptcha();           // mild friction only
    } else {
      enableCheckout();        // clean session
    }
  }
});
javascript — enterprise plan (risk_score + bot)
DevRoute.init({
  apiKey: 'esim_live_YOUR_KEY',
  onResult: function(result) {
    var riskScore  = result.risk_score;   // 0–100
    var isBot      = result.bot;
    var isVpn      = result.vpn;           // Growth+
    var conflicts  = result.signal_conflicts; // array of contradiction strings

    if (isBot || riskScore > 80) {
      blockSession();
    } else if (isVpn || riskScore > 50 || conflicts.length > 1) {
      triggerStepUpVerification();
    } else {
      enableCheckout();
    }
  }
});

Example — Geo Pricing

Display localized prices based on country without a separate geolocation API call.

javascript — enterprise plan
var REGIONAL_PRICES = {
  'US': { amount: '$4.99',  currency: 'USD' },
  'GB': { amount: '£3.99',  currency: 'GBP' },
  'DE': { amount: '€4.49',  currency: 'EUR' },
  'IN': { amount: '₹99',    currency: 'INR' },
};

DevRoute.init({
  apiKey: 'esim_live_YOUR_KEY',
  onResult: function(result) {
    var country = result.geolocation?.country;
    var price   = REGIONAL_PRICES[country] || REGIONAL_PRICES['US'];
    document.getElementById('price-display').textContent = price.amount;
  }
});

Plan Limits

PlanMonthly detectionsPrice
Free1,000$0
Starter25,000$39/mo
Growth100,000$129/mo
Enterprise500,000$399/mo

Limits reset on the 1st of each month. When a limit is reached, the API returns HTTP 429 and detection stops until the next cycle or you upgrade.

See full plan comparison →

Fields by Plan

Fields from higher plans return null on lower plans — no errors, just null values.

PlanAvailable fields
Free id, brand, model, type, confidence, detectionMethod
Starter Free + esim_supported, dual_esim, conversionStrategy, recommendedFlow, esim_osready, family, GPU, networkType, device_tier, device_hash, intelligence.decisions.*, intelligence.narrative.headline, rule_matched, rules_triggered
Growth Starter + IP, isp, vpn, ram, cores, asn, httpProtocol, intelligence.profile, intelligence.authenticity, intelligence.scores
Enterprise Growth + emulator, bot, risk_score, signal_conflicts, timezone_mismatch, country, city, access.*