[{"data":1,"prerenderedAt":2272},["ShallowReactive",2],{"navigation_docs":3,"-docs-fraud-prevention":114,"-docs-fraud-prevention-surround":2267},[4,8,12,16,20,24,28,32,36,40,44,82,86,90,94,98,102,106,110],{"title":5,"path":6,"stem":7},"Overview","\u002Fdocs","docs\u002Findex",{"title":9,"path":10,"stem":11},"Quickstart","\u002Fdocs\u002Fquickstart","docs\u002F01.quickstart",{"title":13,"path":14,"stem":15},"Authentication and keys","\u002Fdocs\u002Fauthentication","docs\u002F02.authentication",{"title":17,"path":18,"stem":19},"Images","\u002Fdocs\u002Fimages","docs\u002F03.images",{"title":21,"path":22,"stem":23},"Texts","\u002Fdocs\u002Ftexts","docs\u002F04.texts",{"title":25,"path":26,"stem":27},"Migrating from SightEngine","\u002Fdocs\u002Fmigrating-from-sightengine","docs\u002F05.migrating-from-sightengine",{"title":29,"path":30,"stem":31},"Workflows","\u002Fdocs\u002Fworkflows","docs\u002F06.workflows",{"title":33,"path":34,"stem":35},"Responses and errors","\u002Fdocs\u002Fresponses-and-errors","docs\u002F07.responses-and-errors",{"title":37,"path":38,"stem":39},"Limits and quotas","\u002Fdocs\u002Flimits-and-quotas","docs\u002F08.limits-and-quotas",{"title":41,"path":42,"stem":43},"The journal and ref","\u002Fdocs\u002Fjournal-and-ref","docs\u002F09.journal-and-ref",{"title":45,"path":46,"stem":47,"children":48,"page":81},"Integration guides","\u002Fdocs\u002Fintegration-guides","docs\u002F10.integration-guides",[49,53,57,61,65,69,73,77],{"title":50,"path":51,"stem":52},"Node.js and TypeScript","\u002Fdocs\u002Fintegration-guides\u002Fnodejs","docs\u002F10.integration-guides\u002F1.nodejs",{"title":54,"path":55,"stem":56},"Python","\u002Fdocs\u002Fintegration-guides\u002Fpython","docs\u002F10.integration-guides\u002F2.python",{"title":58,"path":59,"stem":60},"PHP","\u002Fdocs\u002Fintegration-guides\u002Fphp","docs\u002F10.integration-guides\u002F3.php",{"title":62,"path":63,"stem":64},"Go","\u002Fdocs\u002Fintegration-guides\u002Fgo","docs\u002F10.integration-guides\u002F4.go",{"title":66,"path":67,"stem":68},"Supabase Edge Functions","\u002Fdocs\u002Fintegration-guides\u002Fsupabase-edge-functions","docs\u002F10.integration-guides\u002F5.supabase-edge-functions",{"title":70,"path":71,"stem":72},"Cloudflare Workers","\u002Fdocs\u002Fintegration-guides\u002Fcloudflare-workers","docs\u002F10.integration-guides\u002F6.cloudflare-workers",{"title":74,"path":75,"stem":76},"Nuxt and Next","\u002Fdocs\u002Fintegration-guides\u002Fnuxt-and-next","docs\u002F10.integration-guides\u002F7.nuxt-and-next",{"title":78,"path":79,"stem":80},"Moderate an AI agent","\u002Fdocs\u002Fintegration-guides\u002Fmoderate-ai-agents","docs\u002F10.integration-guides\u002F8.moderate-ai-agents",false,{"title":83,"path":84,"stem":85},"AI coding agents","\u002Fdocs\u002Fai-agents","docs\u002F11.ai-agents",{"title":87,"path":88,"stem":89},"Best practices","\u002Fdocs\u002Fbest-practices","docs\u002F12.best-practices",{"title":91,"path":92,"stem":93},"Privacy and data","\u002Fdocs\u002Fprivacy-and-data","docs\u002F13.privacy-and-data",{"title":95,"path":96,"stem":97},"API reference","\u002Fdocs\u002Fapi-reference","docs\u002F14.api-reference",{"title":99,"path":100,"stem":101},"Fraud prevention","\u002Fdocs\u002Ffraud-prevention","docs\u002F16.fraud-prevention",{"title":103,"path":104,"stem":105},"Device token and challenges","\u002Fdocs\u002Fdevice-and-challenges","docs\u002F17.device-and-challenges",{"title":107,"path":108,"stem":109},"MCP server","\u002Fdocs\u002Fmcp-server","docs\u002F18.mcp-server",{"title":111,"path":112,"stem":113},"Changelog","\u002Fdocs\u002Fchangelog","docs\u002F99.changelog",{"id":115,"title":99,"body":116,"description":2259,"extension":2260,"links":2261,"meta":2262,"navigation":449,"path":100,"seo":2263,"stem":101,"__hash__":2266},"docs\u002Fdocs\u002F16.fraud-prevention.md",{"type":117,"value":118,"toc":2240},"minimark",[119,165,168,171,176,191,247,256,260,266,406,413,693,707,736,860,864,871,970,986,990,1000,1004,1014,1020,1055,1077,1091,1098,1101,1107,1201,1204,1208,1252,1255,1259,1326,1329,1336,1340,1352,1355,1360,1363,1459,1463,1470,1488,1568,1578,1585,1641,1647,1650,1697,1704,1708,1727,1795,1809,1812,1823,1887,1950,2023,2036,2049,2052,2056,2069,2073,2076,2236],[120,121,122,123,130,131,135,136,139,140,143,144,143,147,143,150,143,153,156,157,160,161,164],"p",{},"Stop fake accounts, card testing and abuse with one API. openshield runs ",[124,125,129],"a",{"href":126,"rel":127},"https:\u002F\u002Fgithub.com\u002Fregisandre\u002Fopenfraud-rs",[128],"nofollow","openfraud",", which is open source, for you under ",[132,133,134],"code",{},"\u002Ffraud\u002Fv1",". Call ",[132,137,138],{},"decide"," before a sign-up, a login or a payment, and get ",[132,141,142],{},"allow",", ",[132,145,146],{},"step_up",[132,148,149],{},"review",[132,151,152],{},"hold",[132,154,155],{},"block"," or ",[132,158,159],{},"quarantine"," with the reasons. Call ",[132,162,163],{},"events"," to report what happened.",[120,166,167],{},"It scores IP data (datacenter, VPN, Tor, ASN), disposable email domains, phone numbers, device and browser signals, velocity counters and linked accounts. Every rule shows its reasons, and new rules start in shadow before they act.",[120,169,170],{},"Your organization gets an instance of its own: its events, accounts and cases never mix with anyone else's. It runs on our server in Germany, and your events, decisions and cases are kept 30 days until your first top-up and 90 days after. The fraud API is in beta.",[172,173,175],"h2",{"id":174},"turn-it-on","Turn it on",[120,177,178,179,182,183,186,187,190],{},"An owner or an admin turns it on in the dashboard, under ",[180,181,99],"strong",{},". The instance starts in a few seconds. Then create an API key with fraud access (",[180,184,185],{},"API keys",", then ",[180,188,189],{},"Create","):",[192,193,194,210],"table",{},[195,196,197],"thead",{},[198,199,200,204,207],"tr",{},[201,202,203],"th",{},"Fraud access",[201,205,206],{},"Scope",[201,208,209],{},"What the key may call",[211,212,213,234],"tbody",{},[198,214,215,219,224],{},[216,217,218],"td",{},"Decide and report events only",[216,220,221],{},[132,222,223],{},"fraud_events",[216,225,226,143,228,143,230,233],{},[132,227,138],{},[132,229,163],{},[132,231,232],{},"events\u002Fbatch",", appeals and statements",[198,235,236,239,244],{},[216,237,238],{},"All of it",[216,240,241],{},[132,242,243],{},"fraud",[216,245,246],{},"every route below, cases, accounts, lists and erasure included",[120,248,249,250,252,253,255],{},"A backend that only reports sign-ups and payments needs no more than ",[132,251,223],{},". Keep ",[132,254,243],{}," keys for your back office.",[172,257,259],{"id":258},"decide-before-you-act","Decide before you act",[120,261,262,263,265],{},"Call ",[132,264,138],{}," before a sensitive action (a sign-up, a login, a payment, a message sent to many people) and act on its answer.",[267,268,273],"pre",{"className":269,"code":270,"language":271,"meta":272,"style":272},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","curl -X POST \"https:\u002F\u002Fapi.openshield.dev\u002Ffraud\u002Fv1\u002Fdecide\" \\\n  -H \"Authorization: Bearer $OPENSHIELD_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"type\": \"account.created\",\n    \"actor_id\": \"u_123\",\n    \"email\": \"someone@example.com\",\n    \"ip\": \"203.0.113.50\",\n    \"user_agent\": \"Mozilla\u002F5.0 (Macintosh; Intel Mac OS X 14_6) AppleWebKit\u002F605.1.15 (KHTML, like Gecko) Version\u002F18.0 Safari\u002F605.1.15\",\n    \"language\": \"fr-BE,fr;q=0.9\",\n    \"country\": \"BE\",\n    \"device\": \"dev_8f2c41\"\n  }'\n","bash","",[132,274,275,305,323,337,349,355,361,367,373,379,385,391,397],{"__ignoreMap":272},[276,277,280,284,288,291,295,298,301],"span",{"class":278,"line":279},"line",1,[276,281,283],{"class":282},"sBMFI","curl",[276,285,287],{"class":286},"sfazB"," -X",[276,289,290],{"class":286}," POST",[276,292,294],{"class":293},"sMK4o"," \"",[276,296,297],{"class":286},"https:\u002F\u002Fapi.openshield.dev\u002Ffraud\u002Fv1\u002Fdecide",[276,299,300],{"class":293},"\"",[276,302,304],{"class":303},"sTEyZ"," \\\n",[276,306,308,311,313,316,319,321],{"class":278,"line":307},2,[276,309,310],{"class":286},"  -H",[276,312,294],{"class":293},[276,314,315],{"class":286},"Authorization: Bearer ",[276,317,318],{"class":303},"$OPENSHIELD_KEY",[276,320,300],{"class":293},[276,322,304],{"class":303},[276,324,326,328,330,333,335],{"class":278,"line":325},3,[276,327,310],{"class":286},[276,329,294],{"class":293},[276,331,332],{"class":286},"Content-Type: application\u002Fjson",[276,334,300],{"class":293},[276,336,304],{"class":303},[276,338,340,343,346],{"class":278,"line":339},4,[276,341,342],{"class":286},"  -d",[276,344,345],{"class":293}," '",[276,347,348],{"class":286},"{\n",[276,350,352],{"class":278,"line":351},5,[276,353,354],{"class":286},"    \"type\": \"account.created\",\n",[276,356,358],{"class":278,"line":357},6,[276,359,360],{"class":286},"    \"actor_id\": \"u_123\",\n",[276,362,364],{"class":278,"line":363},7,[276,365,366],{"class":286},"    \"email\": \"someone@example.com\",\n",[276,368,370],{"class":278,"line":369},8,[276,371,372],{"class":286},"    \"ip\": \"203.0.113.50\",\n",[276,374,376],{"class":278,"line":375},9,[276,377,378],{"class":286},"    \"user_agent\": \"Mozilla\u002F5.0 (Macintosh; Intel Mac OS X 14_6) AppleWebKit\u002F605.1.15 (KHTML, like Gecko) Version\u002F18.0 Safari\u002F605.1.15\",\n",[276,380,382],{"class":278,"line":381},10,[276,383,384],{"class":286},"    \"language\": \"fr-BE,fr;q=0.9\",\n",[276,386,388],{"class":278,"line":387},11,[276,389,390],{"class":286},"    \"country\": \"BE\",\n",[276,392,394],{"class":278,"line":393},12,[276,395,396],{"class":286},"    \"device\": \"dev_8f2c41\"\n",[276,398,400,403],{"class":278,"line":399},13,[276,401,402],{"class":286},"  }",[276,404,405],{"class":293},"'\n",[120,407,408,409,412],{},"openfraud's SDKs work as they are: point them at ",[132,410,411],{},"https:\u002F\u002Fapi.openshield.dev\u002Ffraud",".",[267,414,418],{"className":415,"code":416,"language":417,"meta":272,"style":272},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { Client } from \"openfraud\"\n\nconst fraud = new Client({ baseUrl: \"https:\u002F\u002Fapi.openshield.dev\u002Ffraud\", apiKey: process.env.OPENSHIELD_KEY, timeoutMs: 800 })\n\nconst d = await fraud.decide({ type: \"account.created\", actor_id: user.id, email, ip, user_agent, language, country, device })\nif (d.decision === \"block\" || d.decision === \"quarantine\") return refuse()\nif (d.decision === \"step_up\") return askForProof()\n","js",[132,419,420,445,451,525,529,614,666],{"__ignoreMap":272},[276,421,422,426,429,432,435,438,440,442],{"class":278,"line":279},[276,423,425],{"class":424},"s7zQu","import",[276,427,428],{"class":293}," {",[276,430,431],{"class":303}," Client",[276,433,434],{"class":293}," }",[276,436,437],{"class":424}," from",[276,439,294],{"class":293},[276,441,129],{"class":286},[276,443,444],{"class":293},"\"\n",[276,446,447],{"class":278,"line":307},[276,448,450],{"emptyLinePlaceholder":449},true,"\n",[276,452,453,457,460,463,466,469,472,475,479,482,484,486,488,491,494,496,499,501,504,506,509,511,514,516,520,522],{"class":278,"line":325},[276,454,456],{"class":455},"spNyl","const",[276,458,459],{"class":303}," fraud ",[276,461,462],{"class":293},"=",[276,464,465],{"class":293}," new",[276,467,431],{"class":468},"s2Zo4",[276,470,471],{"class":303},"(",[276,473,474],{"class":293},"{",[276,476,478],{"class":477},"swJcz"," baseUrl",[276,480,481],{"class":293},":",[276,483,294],{"class":293},[276,485,411],{"class":286},[276,487,300],{"class":293},[276,489,490],{"class":293},",",[276,492,493],{"class":477}," apiKey",[276,495,481],{"class":293},[276,497,498],{"class":303}," process",[276,500,412],{"class":293},[276,502,503],{"class":303},"env",[276,505,412],{"class":293},[276,507,508],{"class":303},"OPENSHIELD_KEY",[276,510,490],{"class":293},[276,512,513],{"class":477}," timeoutMs",[276,515,481],{"class":293},[276,517,519],{"class":518},"sbssI"," 800",[276,521,434],{"class":293},[276,523,524],{"class":303},")\n",[276,526,527],{"class":278,"line":339},[276,528,450],{"emptyLinePlaceholder":449},[276,530,531,533,536,538,541,544,546,548,550,552,555,557,559,562,564,566,569,571,574,576,579,581,584,586,589,591,594,596,599,601,604,606,609,612],{"class":278,"line":351},[276,532,456],{"class":455},[276,534,535],{"class":303}," d ",[276,537,462],{"class":293},[276,539,540],{"class":424}," await",[276,542,543],{"class":303}," fraud",[276,545,412],{"class":293},[276,547,138],{"class":468},[276,549,471],{"class":303},[276,551,474],{"class":293},[276,553,554],{"class":477}," type",[276,556,481],{"class":293},[276,558,294],{"class":293},[276,560,561],{"class":286},"account.created",[276,563,300],{"class":293},[276,565,490],{"class":293},[276,567,568],{"class":477}," actor_id",[276,570,481],{"class":293},[276,572,573],{"class":303}," user",[276,575,412],{"class":293},[276,577,578],{"class":303},"id",[276,580,490],{"class":293},[276,582,583],{"class":303}," email",[276,585,490],{"class":293},[276,587,588],{"class":303}," ip",[276,590,490],{"class":293},[276,592,593],{"class":303}," user_agent",[276,595,490],{"class":293},[276,597,598],{"class":303}," language",[276,600,490],{"class":293},[276,602,603],{"class":303}," country",[276,605,490],{"class":293},[276,607,608],{"class":303}," device ",[276,610,611],{"class":293},"}",[276,613,524],{"class":303},[276,615,616,619,622,624,627,630,632,634,636,639,642,644,646,648,650,652,654,657,660,663],{"class":278,"line":357},[276,617,618],{"class":424},"if",[276,620,621],{"class":303}," (d",[276,623,412],{"class":293},[276,625,626],{"class":303},"decision ",[276,628,629],{"class":293},"===",[276,631,294],{"class":293},[276,633,155],{"class":286},[276,635,300],{"class":293},[276,637,638],{"class":293}," ||",[276,640,641],{"class":303}," d",[276,643,412],{"class":293},[276,645,626],{"class":303},[276,647,629],{"class":293},[276,649,294],{"class":293},[276,651,159],{"class":286},[276,653,300],{"class":293},[276,655,656],{"class":303},") ",[276,658,659],{"class":424},"return",[276,661,662],{"class":468}," refuse",[276,664,665],{"class":303},"()\n",[276,667,668,670,672,674,676,678,680,682,684,686,688,691],{"class":278,"line":363},[276,669,618],{"class":424},[276,671,621],{"class":303},[276,673,412],{"class":293},[276,675,626],{"class":303},[276,677,629],{"class":293},[276,679,294],{"class":293},[276,681,146],{"class":286},[276,683,300],{"class":293},[276,685,656],{"class":303},[276,687,659],{"class":424},[276,689,690],{"class":468}," askForProof",[276,692,665],{"class":303},[120,694,695,696,699,700,703,704,706],{},"The SDKs fail open: on a timeout, a ",[132,697,698],{},"429"," or a ",[132,701,702],{},"5xx"," they retry, then answer ",[132,705,142],{},". Give them at least 800 ms: a call goes through openshield's edge before it reaches your instance.",[120,708,709,710,713,714,143,716,143,718,143,720,143,722,156,724,726,727,730,731,735],{},"The answer has the ",[132,711,712],{},"decision"," (",[132,715,142],{},[132,717,146],{},[132,719,149],{},[132,721,152],{},[132,723,155],{},[132,725,159],{},"), the rules that fired and why, the ",[132,728,729],{},"actions"," to apply, and the case it opened, if any. openfraud's ",[124,732,95],{"href":733,"rel":734},"https:\u002F\u002Fgithub.com\u002Fregisandre\u002Fopenfraud-rs\u002Fblob\u002Fmain\u002Fdocs\u002Fapi.md",[128]," describes every field. Besides those, the answer carries:",[192,737,738,748],{},[195,739,740],{},[198,741,742,745],{},[201,743,744],{},"Field",[201,746,747],{},"What it holds",[211,749,750,770,790,803,816,844],{},[198,751,752,757],{},[216,753,754],{},[132,755,756],{},"signals",[216,758,759,760,143,763,143,766,769],{},"what the facts show (",[132,761,762],{},"new_device",[132,764,765],{},"tor_ip",[132,767,768],{},"disposable_email_domain","...), and the signal of every rule that fired, acting or in shadow",[198,771,772,777],{},[216,773,774],{},[132,775,776],{},"scores",[216,778,779,143,782,785,786,789],{},[132,780,781],{},"account_takeover",[132,783,784],{},"account_abuse"," and ",[132,787,788],{},"bot",", each from 0 to 1: a summary of the rules that fired, by family",[198,791,792,797],{},[216,793,794],{},[132,795,796],{},"lists",[216,798,799,800],{},"the lists this event changed, as ",[132,801,802],{},"[{\"list\": \"trusted_devices\", \"action\": \"add\"}]",[198,804,805,810],{},[216,806,807],{},[132,808,809],{},"stopped_by",[216,811,812,813],{},"the allow rule that allowed the event over the other rules, or ",[132,814,815],{},"null",[198,817,818,823],{},[216,819,820],{},[132,821,822],{},"matched_actor",[216,824,825,826,829,830,832,833,835,836,838,839,843],{},"for an event sent before sign-in (no ",[132,827,828],{},"actor","), the account its email address belongs to, when there is one. Only a ",[132,831,243],{}," key sees it: a ",[132,834,223],{}," key gets ",[132,837,815],{},". It is information: never act on that account from it (see ",[124,840,842],{"href":841},"#before-sign-in-and-events-a-page-reports","before sign-in",")",[198,845,846,851],{},[216,847,848],{},[132,849,850],{},"sandbox",[216,852,853,856,857],{},[132,854,855],{},"true"," when the answer comes from your ",[124,858,850],{"href":859},"#sandbox",[172,861,863],{"id":862},"send-the-end-users-context-not-your-servers","Send the end user's context, not your server's",[120,865,866,867,870],{},"The gateway passes your request body to your instance untouched. It never fills these fields from its own request: that request comes from your backend, and its address, ",[132,868,869],{},"User-Agent"," and language describe your server.",[192,872,873,882],{},[195,874,875],{},[198,876,877,879],{},[201,878,744],{},[201,880,881],{},"What to send",[211,883,884,898,918,931,947],{},[198,885,886,891],{},[216,887,888],{},[132,889,890],{},"ip",[216,892,893,894,897],{},"The end user's address. Behind a proxy, the first ",[132,895,896],{},"X-Forwarded-For"," entry you trust.",[198,899,900,905],{},[216,901,902],{},[132,903,904],{},"user_agent",[216,906,907,908,910,911,143,914,917],{},"The browser's ",[132,909,869],{}," header. Your backend's own (",[132,912,913],{},"node",[132,915,916],{},"python-requests",") makes every event look scripted.",[198,919,920,925],{},[216,921,922],{},[132,923,924],{},"language",[216,926,907,927,930],{},[132,928,929],{},"Accept-Language"," header.",[198,932,933,938],{},[216,934,935],{},[132,936,937],{},"country",[216,939,940,941,143,944,412],{},"From your CDN: ",[132,942,943],{},"CF-IPCountry",[132,945,946],{},"CloudFront-Viewer-Country",[198,948,949,954],{},[216,950,951],{},[132,952,953],{},"device",[216,955,956,957,962,963,966,967,412],{},"The id from openfraud's ",[124,958,961],{"href":959,"rel":960},"https:\u002F\u002Fgithub.com\u002Fregisandre\u002Fopenfraud-rs\u002Ftree\u002Fmain\u002Fsdk\u002Fdevice",[128],"device script",", and ",[132,964,965],{},"attrs.webdriver"," from its ",[132,968,969],{},"automated()",[120,971,972,143,975,143,978,785,980,982,983,985],{},[132,973,974],{},"email",[132,976,977],{},"phone",[132,979,890],{},[132,981,953],{}," are replaced by keyed pseudonyms before any rule sees them, and the raw values are not stored. The ",[132,984,869],{}," is read for the browser, the system and the signs of automation, then dropped.",[172,987,989],{"id":988},"report-what-happened","Report what happened",[120,991,992,995,996,999],{},[132,993,994],{},"POST \u002Ffraud\u002Fv1\u002Fevents"," reports an event after the fact (a payment that went through, a refund, a dispute) without waiting for a decision. ",[132,997,998],{},"POST \u002Ffraud\u002Fv1\u002Fevents\u002Fbatch"," takes up to 100 at once. Rules learn from these: a card used by many accounts, a trial taken again and again.",[172,1001,1003],{"id":1002},"before-sign-in-and-events-a-page-reports","Before sign-in, and events a page reports",[120,1005,1006,1007,1009,1010,1013],{},"Before sign-in there is no account to name: send a failed login or a password reset with the ",[132,1008,974],{}," the person typed, and no ",[132,1011,1012],{},"actor_id",". Anyone can type someone else's address, so such an event is evidence about the sender, never about the account it matches. Your instance counts it under the sender's address, network, device and email domain, and never under the account: a burst of attempts with someone's address cannot change that account's decisions, counters, lists or trusted devices.",[120,1015,1016,1017,481],{},"Each event says who saw it happen, in ",[132,1018,1019],{},"reported_by",[192,1021,1022,1032],{},[195,1023,1024],{},[198,1025,1026,1029],{},[201,1027,1028],{},"Value",[201,1030,1031],{},"When",[211,1033,1034,1045],{},[198,1035,1036,1042],{},[216,1037,1038,1041],{},[132,1039,1040],{},"server"," (the default)",[216,1043,1044],{},"your backend saw it and knows who is signed in: a login it checked, a payment it took",[198,1046,1047,1052],{},[216,1048,1049],{},[132,1050,1051],{},"client",[216,1053,1054],{},"your page or app sent it, and your backend only passes it on without checking who is signed in",[120,1056,1057,1058,1060,1061,143,1063,785,1066,1069,1070,1073,1074,412],{},"A ",[132,1059,1051],{}," event is treated like one before sign-in: its ",[132,1062,1012],{},[132,1064,1065],{},"tenant_id",[132,1067,1068],{},"owner_id"," are dropped, since a page can claim any of them. If your front end reports events (a page view, a form opened before sign-in) through your backend, mark them ",[132,1071,1072],{},"\"reported_by\": \"client\"",". Any other value is refused with a ",[132,1075,1076],{},"400",[120,1078,1079,1080,785,1083,1086,1087,1090],{},"Send ",[132,1081,1082],{},"challenge.succeeded",[132,1084,1085],{},"challenge.failed"," from your server, after it checked the proof itself, never relayed from the page: only a server-reported pass trusts the device (see ",[124,1088,1089],{"href":104},"step-up challenges",").",[120,1092,1093,1094,1097],{},"Rules read ",[132,1095,1096],{},"event.reported_by"," too, so a rule of yours can weigh or leave out the events a page reported.",[172,1099,1100],{"id":796},"Lists",[120,1102,1103,1104,1106],{},"Lists hold the values your rules match: accounts, devices, emails, addresses. Read and fill them with a ",[132,1105,243],{}," key:",[192,1108,1109,1119],{},[195,1110,1111],{},[198,1112,1113,1116],{},[201,1114,1115],{},"Route",[201,1117,1118],{},"What it does",[211,1120,1121,1131,1145,1167,1177,1191],{},[198,1122,1123,1128],{},[216,1124,1125],{},[132,1126,1127],{},"GET \u002Ffraud\u002Fv1\u002Flists",[216,1129,1130],{},"your lists",[198,1132,1133,1138],{},[216,1134,1135],{},[132,1136,1137],{},"GET \u002Ffraud\u002Fv1\u002Flists\u002F{name}\u002Fitems",[216,1139,1140,1141,1144],{},"the items added at run time, with their author, end and note (",[132,1142,1143],{},"?archived=true"," includes the archived ones)",[198,1146,1147,1152],{},[216,1148,1149],{},[132,1150,1151],{},"POST \u002Ffraud\u002Fv1\u002Flists\u002F{name}\u002Fitems",[216,1153,1154,1155,1158,1159,1162,1163,1166],{},"adds items, each a string or ",[132,1156,1157],{},"{\"value\", \"second\", \"for\", \"note\"}","; ",[132,1160,1161],{},"for"," (for example ",[132,1164,1165],{},"7d",") overrides the list's expiry",[198,1168,1169,1174],{},[216,1170,1171],{},[132,1172,1173],{},"DELETE \u002Ffraud\u002Fv1\u002Flists\u002F{name}\u002Fitems?item=...",[216,1175,1176],{},"removes an item",[198,1178,1179,1184],{},[216,1180,1181],{},[132,1182,1183],{},"POST \u002Ffraud\u002Fv1\u002Flists\u002F{name}\u002Fitems\u002Farchive",[216,1185,1186,1187,1190],{},"archives items, given as the ",[132,1188,1189],{},"entries"," of the list show them: they stop matching and stay on record",[198,1192,1193,1198],{},[216,1194,1195],{},[132,1196,1197],{},"POST \u002Ffraud\u002Fv1\u002Flists\u002F{name}\u002Fitems\u002Funarchive",[216,1199,1200],{},"gives archived items back",[120,1202,1203],{},"A list is read item by item: it cannot be exported as a file.",[172,1205,1207],{"id":1206},"look-up-an-ip-address","Look up an IP address",[120,1209,1210,1213,1214,1217,1218,143,1221,143,1224,1226,1227,1229,1230,1233,1234,1237,1238,1241,1242,1244,1245,1248,1249,1251],{},[132,1211,1212],{},"GET \u002Ffraud\u002Fv1\u002Fips\u002F{ip}"," answers what your instance knows of an address: its ",[132,1215,1216],{},"type",", its network (",[132,1219,1220],{},"asn",[132,1222,1223],{},"org",[132,1225,937],{},") and the ",[132,1228,796],{}," that hold it. ",[132,1231,1232],{},"POST \u002Ffraud\u002Fv1\u002Fips\u002Fquery"," does the same for up to 1,000 addresses, sent as ",[132,1235,1236],{},"{\"ips\": [\"203.0.113.50\", \"198.51.100.7\"]}",", and answers ",[132,1239,1240],{},"{results, meta: {total, valid}}",", with the invalid ones left out. A longer batch is refused with ",[132,1243,1076],{}," ",[132,1246,1247],{},"too_many_ips",". Both need a ",[132,1250,243],{}," key.",[120,1253,1254],{},"A lookup is billed for each valid address it answers for, not for the ones that were left out. A batch reserves the price of 1,000 lookups from your balance before it runs, and gives back what it did not use.",[172,1256,1258],{"id":1257},"prices","Prices",[192,1260,1261,1271],{},[195,1262,1263],{},[198,1264,1265,1268],{},[201,1266,1267],{},"Call",[201,1269,1270],{},"Price",[211,1272,1273,1284,1296,1310,1318],{},[198,1274,1275,1281],{},[216,1276,1277,1278,843],{},"Decision (",[132,1279,1280],{},"\u002Ffraud\u002Fv1\u002Fdecide",[216,1282,1283],{},"EUR 0.001",[198,1285,1286,1293],{},[216,1287,1288,1289,1292],{},"Event (",[132,1290,1291],{},"\u002Ffraud\u002Fv1\u002Fevents",", each accepted event of a batch)",[216,1294,1295],{},"EUR 0.0002",[198,1297,1298,1308],{},[216,1299,1300,1301,1304,1305,843],{},"IP lookup (",[132,1302,1303],{},"\u002Ffraud\u002Fv1\u002Fips\u002F{ip}",", each valid address of ",[132,1306,1307],{},"ips\u002Fquery",[216,1309,1295],{},[198,1311,1312,1315],{},[216,1313,1314],{},"With the network data on, each decision",[216,1316,1317],{},"+ EUR 0.0002",[198,1319,1320,1323],{},[216,1321,1322],{},"With the activity bursts on, each decision",[216,1324,1325],{},"+ EUR 0.0005",[120,1327,1328],{},"The network data and the activity bursts hold more in your instance's memory, so a decision costs more while they are on. You turn them on and off in the fraud settings of the dashboard.",[120,1330,1331,1332,1335],{},"Every price comes from the same prepaid balance as the checks, the monthly free use included. A call that does not end in a ",[132,1333,1334],{},"2xx"," costs nothing. The other routes (cases, accounts and lists) are free.",[172,1337,1339],{"id":1338},"what-your-instance-checks","What your instance checks",[120,1341,1342,1343,1346,1347,1351],{},"The core always runs: blocklists you fill, trust earned by paying, and account takeover signals. In the dashboard you add rule packs for the kind of abuse you see: free tiers and trials, cards and payments, messaging, marketplaces and payouts, APIs and compute, hosting and content. Every pack rule starts in shadow: it says what it would do, in ",[132,1344,1345],{},"shadow",", without doing it, until it is promoted to act. ",[124,1348,1350],{"href":1349},"#when-rules-start-to-act","When rules start to act"," says how.",[120,1353,1354],{},"The network data (the operator and country of each address, and the lists of disposable email domains, Tor exits, data centres and VPNs) comes with your first top-up. openshield refreshes it once a day, and your instance downloads it from inside the node: it reaches nothing on the internet.",[1356,1357,1359],"h3",{"id":1358},"settings","Settings",[120,1361,1362],{},"Four more settings sit next to the packs in the dashboard.",[1364,1365,1366,1383,1393,1403],"ul",{},[1367,1368,1369,1372,1373,143,1376,785,1379,1382],"li",{},[180,1370,1371],{},"Activity bursts"," (from your first top-up, off by default). Flags an account, a device or an address that sends far more events than its usual hour: the signals ",[132,1374,1375],{},"high_activity_account",[132,1377,1378],{},"high_activity_device",[132,1380,1381],{},"high_activity_ip",". It keeps 7 days of counters, so the memory it uses grows with your traffic.",[1367,1384,1385,1388,1389,1392],{},[180,1386,1387],{},"Email domain check"," (from your first top-up, off by default). Asks DNS whether the domain of an email address takes mail, once a day per domain, and raises ",[132,1390,1391],{},"unreachable_email"," when it does not. It sends the domain only, never the address, through a resolver inside the node. It uses DNS only, no extra memory.",[1367,1394,1395,1398,1399,1402],{},[180,1396,1397],{},"Require the device token"," (off by default). An event without a ",[132,1400,1401],{},"device_token"," counts as missing. Turn it on once every page sends the device token.",[1367,1404,1405,1408,1409,143,1412,143,1415,143,1418,143,1421,143,1424,143,1427,143,1430,143,1433,143,1436,143,1439,143,1442,143,1445,1448,1449,143,1452,785,1455,1458],{},[180,1406,1407],{},"Webhook types"," (all by default). Narrow the types posted to your webhook address. The types are ",[132,1410,1411],{},"decision.step_up",[132,1413,1414],{},"decision.review",[132,1416,1417],{},"decision.hold",[132,1419,1420],{},"decision.block",[132,1422,1423],{},"decision.quarantine",[132,1425,1426],{},"case.opened",[132,1428,1429],{},"case.updated",[132,1431,1432],{},"case.resolved",[132,1434,1435],{},"case.appealed",[132,1437,1438],{},"actor.status_changed",[132,1440,1441],{},"tenant.status_changed",[132,1443,1444],{},"brake.engaged",[132,1446,1447],{},"brake.released",", and the three list types, ",[132,1450,1451],{},"list_item.created",[132,1453,1454],{},"list_item.archived",[132,1456,1457],{},"list_item.unarchived",", which are posted when an item is added to a list, archived or restored. While you keep all of them, a type added in a later release reaches you; once you narrow the list, you receive only the types you ticked.",[172,1460,1462],{"id":1461},"vpn-and-residential-proxies","VPN and residential proxies",[120,1464,1465,1466,1469],{},"The network data tells a data centre or a Tor exit. A VPN exit and a residential proxy (a home connection rented out to hide who sits behind it) need fresher data, so openshield looks the address up when the event comes in. Turn on ",[180,1467,1468],{},"VPN and residential proxy facts"," in the dashboard, from your first top-up. It is off by default, and it costs nothing more: the lookup is included in the price of the call.",[120,1471,1472,1473,1476,1477,1479,1480,143,1482,785,1484,1487],{},"When it is on, openshield adds four attributes to the ",[132,1474,1475],{},"attrs"," of an event that has an ",[132,1478,890],{},", on ",[132,1481,1280],{},[132,1483,1291],{},[132,1485,1486],{},"\u002Ffraud\u002Fv1\u002Fevents\u002Fbatch",", before the event reaches your instance:",[192,1489,1490,1500],{},[195,1491,1492],{},[198,1493,1494,1497],{},[201,1495,1496],{},"Attribute",[201,1498,1499],{},"Values",[211,1501,1502,1526,1548,1558],{},[198,1503,1504,1509],{},[216,1505,1506],{},[132,1507,1508],{},"attrs.os_ip_tunnel",[216,1510,1511,143,1514,143,1517,143,1520,156,1523],{},[132,1512,1513],{},"vpn",[132,1515,1516],{},"proxy",[132,1518,1519],{},"tor",[132,1521,1522],{},"relay",[132,1524,1525],{},"none",[198,1527,1528,1533],{},[216,1529,1530],{},[132,1531,1532],{},"attrs.os_proxy_type",[216,1534,1535,143,1538,143,1541,156,1544,1547],{},[132,1536,1537],{},"residential",[132,1539,1540],{},"datacenter",[132,1542,1543],{},"isp",[132,1545,1546],{},"unknown","; a line is classed only when a tunnel was detected",[198,1549,1550,1555],{},[216,1551,1552],{},[132,1553,1554],{},"attrs.os_tunnel_operator",[216,1556,1557],{},"the name of the service that runs the address, when known",[198,1559,1560,1565],{},[216,1561,1562],{},[132,1563,1564],{},"attrs.os_tunnel_last_seen_days",[216,1566,1567],{},"whole days since the address was last seen acting as a tunnel, when known",[120,1569,1570,1571,1574,1575,1577],{},"The ",[132,1572,1573],{},"os_"," prefix is openshield's: an attribute you send under another name is never touched, and one you send under an ",[132,1576,1573],{}," name is replaced by the lookup's own. Without the setting, or when the lookup does not answer within 300 ms, the event goes through exactly as you sent it: a slow or failed lookup never refuses an event, it only leaves the attributes out. An address is looked up once a day.",[120,1579,1580,1581,1584],{},"Two rules read the attributes, in the ",[132,1582,1583],{},"openshield-tunnels"," rules that join your instance with the setting. Both start in shadow, like every pack rule:",[192,1586,1587,1600],{},[195,1588,1589],{},[198,1590,1591,1594,1597],{},[201,1592,1593],{},"Rule",[201,1595,1596],{},"Signal",[201,1598,1599],{},"Fires when",[211,1601,1602,1623],{},[198,1603,1604,1609,1614],{},[216,1605,1606],{},[132,1607,1608],{},"residential_proxy",[216,1610,1611,1613],{},[132,1612,1608],{}," (abuse)",[216,1615,1616,1619,1620,1622],{},[132,1617,1618],{},"os_proxy_type"," is ",[132,1621,1537],{}," and the address was last seen 7 days ago or less, or the days are unknown",[198,1624,1625,1630,1634],{},[216,1626,1627],{},[132,1628,1629],{},"vpn_tunnel",[216,1631,1632],{},[132,1633,1629],{},[216,1635,1636,1619,1639],{},[132,1637,1638],{},"os_ip_tunnel",[132,1640,1513],{},[120,1642,1643,1644,1646],{},"A VPN is no proof of fraud (many honest users run one), so ",[132,1645,1629],{}," weighs little; read it with the other signals. The facts come from a third-party data source (proxycheck.io), which openshield sends the address and nothing else of the event. Its data is never exposed: your instance gets the four attributes above for the address of each event, and neither the source's lists nor its answers are served to you or to anyone else.",[172,1648,1350],{"id":1649},"when-rules-start-to-act",[1364,1651,1652,1661,1667,1673,1679,1685,1691],{},[1367,1653,1654,1657,1658,1660],{},[180,1655,1656],{},"Day 1."," The core blocklists act from the first call. Every other rule starts in shadow: the answer lists what it would have done under ",[132,1659,1345],{},", and nothing is blocked because of it.",[1367,1662,1663,1666],{},[180,1664,1665],{},"Automatic promotion, on by default."," Every day after the first 30, openshield looks at each shadow rule that hit at least 20 accounts, and promotes it to act when it has proved reliable. Either you labelled the accounts it hit, with a precision of at least 95 % over at least 10 labelled accounts, or our decision model reviewed pseudonymized timelines of up to 10 accounts the rule hit and found at least 90 % of them fraudulent.",[1367,1668,1669,1672],{},[180,1670,1671],{},"What a promoted rule may do."," Whatever the rule is built for, a block included.",[1367,1674,1675,1678],{},[180,1676,1677],{},"Manual mode."," You can switch to manual promotion, so that a rule acts only when a person promotes it. Or you can keep automatic promotion but limit it to rules whose action is hold or review, so that a rule that blocks is promoted by a person only.",[1367,1680,1681,1684],{},[180,1682,1683],{},"You are told."," Every automatic promotion is emailed to you and recorded in the audit log.",[1367,1686,1687,1690],{},[180,1688,1689],{},"A brake."," A brake stops the acting rules when a spike of decisions shows up.",[1367,1692,1693,1696],{},[180,1694,1695],{},"Back to shadow."," A promoted rule whose labelled precision falls under 80 % goes back to shadow on its own.",[120,1698,1699,1700,1703],{},"Labelling the accounts you know to be fraud or legitimate (",[132,1701,1702],{},"POST \u002Ffraud\u002Fv1\u002Factors\u002F{id}\u002Flabel",") is what makes promotion reliable, and what demotes a rule that has gone wrong.",[172,1705,1707],{"id":1706},"webhooks","Webhooks",[120,1709,1710,1711,1713,1714,143,1716,143,1718,1720,1721,1726],{},"Set a webhook address in the dashboard. Every decision other than ",[132,1712,142],{},", every change to a case, an account or a workspace, and every item added to a list, archived or given back (",[132,1715,1451],{},[132,1717,1454],{},[132,1719,1457],{},"), is posted to it, signed with the ",[124,1722,1725],{"href":1723,"rel":1724},"https:\u002F\u002Fwww.standardwebhooks.com",[128],"Standard Webhooks"," scheme under the secret the dashboard shows. Any Standard Webhooks library checks them, as does the SDK:",[267,1728,1730],{"className":415,"code":1729,"language":417,"meta":272,"style":272},"import { verifyWebhook } from \"openfraud\"\n\nconst event = await verifyWebhook(process.env.OPENSHIELD_FRAUD_WEBHOOK_SECRET, req.headers, rawBody)\n",[132,1731,1732,1751,1755],{"__ignoreMap":272},[276,1733,1734,1736,1738,1741,1743,1745,1747,1749],{"class":278,"line":279},[276,1735,425],{"class":424},[276,1737,428],{"class":293},[276,1739,1740],{"class":303}," verifyWebhook",[276,1742,434],{"class":293},[276,1744,437],{"class":424},[276,1746,294],{"class":293},[276,1748,129],{"class":286},[276,1750,444],{"class":293},[276,1752,1753],{"class":278,"line":307},[276,1754,450],{"emptyLinePlaceholder":449},[276,1756,1757,1759,1762,1764,1766,1768,1771,1773,1775,1777,1780,1782,1785,1787,1790,1792],{"class":278,"line":325},[276,1758,456],{"class":455},[276,1760,1761],{"class":303}," event ",[276,1763,462],{"class":293},[276,1765,540],{"class":424},[276,1767,1740],{"class":468},[276,1769,1770],{"class":303},"(process",[276,1772,412],{"class":293},[276,1774,503],{"class":303},[276,1776,412],{"class":293},[276,1778,1779],{"class":303},"OPENSHIELD_FRAUD_WEBHOOK_SECRET",[276,1781,490],{"class":293},[276,1783,1784],{"class":303}," req",[276,1786,412],{"class":293},[276,1788,1789],{"class":303},"headers",[276,1791,490],{"class":293},[276,1793,1794],{"class":303}," rawBody)\n",[120,1796,1797,1798,1800,1801,1804,1805,1808],{},"Answer with a ",[132,1799,1334],{}," within 10 seconds. A webhook that is not delivered is sent again for about two days, under the same ",[132,1802,1803],{},"webhook-id","; a ",[132,1806,1807],{},"410"," stops it.",[172,1810,1811],{"id":850},"Sandbox",[120,1813,1814,1815,1818,1819,1822],{},"Test your integration without touching your live data. Create an API key and pick ",[180,1816,1817],{},"Test"," as its environment: you get an ",[132,1820,1821],{},"om_test_"," key, which reaches a sandbox of your own and nothing else. The sandbox is a separate instance, with no rule pack and no network data, so it never sees your live accounts, lists or cases, and a live key never reaches it.",[1364,1824,1825,1842,1860,1877],{},[1367,1826,1827,1830,1831,1833,1834,156,1836,1838,1839,412],{},[180,1828,1829],{},"Keys."," An ",[132,1832,1821],{}," key has the ",[132,1835,243],{},[132,1837,223],{}," scope, for all of the sandbox, and is refused by the moderation API. It counts apart from your live keys against the key limit your top-ups give. Send it the way you send a live key: ",[132,1840,1841],{},"Authorization: Bearer om_test_...",[1367,1843,1844,1847,1848,1244,1850,1853,1854,1244,1856,1859],{},[180,1845,1846],{},"Free, with limits."," Each organization may send the sandbox 5 requests a second and 10,000 calls a month (decisions, events and IP lookups, a batch counting each event or address). Past the rate you get ",[132,1849,698],{},[132,1851,1852],{},"rate_limited","; past the month you get ",[132,1855,698],{},[132,1857,1858],{},"sandbox_quota_exceeded",", until the 1st of the next month (UTC). Reading cases, lists and accounts is not counted. Nothing is taken from your balance.",[1367,1861,1862,1865,1866,1244,1869,1872,1873,1876],{},[180,1863,1864],{},"On first use."," The sandbox starts with its first call, which gets ",[132,1867,1868],{},"503",[132,1870,1871],{},"fraud_waking"," with ",[132,1874,1875],{},"Retry-After: 5",", and is paused after 7 days without a call. The next call wakes it. It keeps its events 30 days.",[1367,1878,1879,1882,1883,1886],{},[180,1880,1881],{},"Mock tokens."," A device token that starts with ",[132,1884,1885],{},"test|"," sets the answer, so you can drive every branch of your code without writing a rule:",[267,1888,1892],{"className":1889,"code":1890,"language":1891,"meta":272,"style":272},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{ \"type\": \"session.login\", \"actor_id\": \"u_1\", \"device_token\": \"test|device:d1|verdict:deny|score:80|ip:BE\" }\n","json",[132,1893,1894],{"__ignoreMap":272},[276,1895,1896,1898,1900,1902,1904,1906,1908,1911,1913,1915,1917,1919,1921,1923,1925,1928,1930,1932,1934,1936,1938,1940,1942,1945,1947],{"class":278,"line":279},[276,1897,474],{"class":293},[276,1899,294],{"class":293},[276,1901,1216],{"class":455},[276,1903,300],{"class":293},[276,1905,481],{"class":293},[276,1907,294],{"class":293},[276,1909,1910],{"class":286},"session.login",[276,1912,300],{"class":293},[276,1914,490],{"class":293},[276,1916,294],{"class":293},[276,1918,1012],{"class":455},[276,1920,300],{"class":293},[276,1922,481],{"class":293},[276,1924,294],{"class":293},[276,1926,1927],{"class":286},"u_1",[276,1929,300],{"class":293},[276,1931,490],{"class":293},[276,1933,294],{"class":293},[276,1935,1401],{"class":455},[276,1937,300],{"class":293},[276,1939,481],{"class":293},[276,1941,294],{"class":293},[276,1943,1944],{"class":286},"test|device:d1|verdict:deny|score:80|ip:BE",[276,1946,300],{"class":293},[276,1948,1949],{"class":293}," }\n",[192,1951,1952,1962],{},[195,1953,1954],{},[198,1955,1956,1959],{},[201,1957,1958],{},"Part",[201,1960,1961],{},"Meaning",[211,1963,1964,1973,1997,2011],{},[198,1965,1966,1970],{},[216,1967,1968],{},[132,1969,953],{},[216,1971,1972],{},"the device id, up to 64 characters",[198,1974,1975,1980],{},[216,1976,1977],{},[132,1978,1979],{},"verdict",[216,1981,1982,143,1984,1987,1988,1990,1991,1987,1994,1996],{},[132,1983,142],{},[132,1985,1986],{},"challenge"," (as ",[132,1989,146],{},"), ",[132,1992,1993],{},"deny",[132,1995,155],{},"), or any decision name",[198,1998,1999,2004],{},[216,2000,2001],{},[132,2002,2003],{},"score",[216,2005,2006,2007,2010],{},"0 to 1,000 (or ",[132,2008,2009],{},"risk",", 0 to 1)",[198,2012,2013,2017],{},[216,2014,2015],{},[132,2016,890],{},[216,2018,2019,2020],{},"a country for the event, such as ",[132,2021,2022],{},"BE",[120,2024,2025,2026,2029,2030,2032,2033,412],{},"The answer carries the rule ",[132,2027,2028],{},"sandbox_mock",". On your live instance, a ",[132,2031,1885],{}," token is ",[132,2034,2035],{},"invalid",[1364,2037,2038],{},[1367,2039,2040,2043,2044,785,2046,2048],{},[180,2041,2042],{},"Webhooks."," The sandbox's webhooks go to a test address you set in the dashboard, under ",[180,2045,99],{},[180,2047,1811],{},", signed with a test secret of their own. Nothing from the sandbox reaches your live address, and nothing from your live instance reaches the test one.",[120,2050,2051],{},"The dashboard shows the sandbox's state (off, running, paused), the calls of the month out of 10,000, the test address and its secret.",[172,2053,2055],{"id":2054},"a-paused-instance","A paused instance",[120,2057,2058,2059,1244,2061,1872,2063,2065,2066,2068],{},"A free organization's instance is paused after 30 days without a call: its data is kept. The next call wakes it and gets ",[132,2060,1868],{},[132,2062,1871],{},[132,2064,1875],{},", and the SDKs answer ",[132,2067,142],{}," meanwhile. An owner or an admin can also resume it from the dashboard.",[172,2070,2072],{"id":2071},"errors","Errors",[120,2074,2075],{},"These answers come from openshield; every other one is your instance's own, in openfraud's envelope.",[192,2077,2078,2090],{},[195,2079,2080],{},[198,2081,2082,2085,2088],{},[201,2083,2084],{},"Status",[201,2086,2087],{},"Code",[201,2089,1031],{},[211,2091,2092,2108,2123,2143,2158,2172,2187,2202,2218],{},[198,2093,2094,2098,2102],{},[216,2095,2096],{},[132,2097,1076],{},[216,2099,2100],{},[132,2101,1247],{},[216,2103,2104,2105,2107],{},"an ",[132,2106,1307],{}," batch holds more than 1,000 addresses",[198,2109,2110,2115,2120],{},[216,2111,2112],{},[132,2113,2114],{},"401",[216,2116,2117],{},[132,2118,2119],{},"unauthorized",[216,2121,2122],{},"no key, or a wrong one",[198,2124,2125,2130,2135],{},[216,2126,2127],{},[132,2128,2129],{},"403",[216,2131,2132],{},[132,2133,2134],{},"forbidden",[216,2136,2137,2138,2140,2141],{},"the key has no fraud access, or only ",[132,2139,223],{}," for a route that needs ",[132,2142,243],{},[198,2144,2145,2150,2155],{},[216,2146,2147],{},[132,2148,2149],{},"404",[216,2151,2152],{},[132,2153,2154],{},"fraud_not_enabled",[216,2156,2157],{},"your organization has not turned fraud prevention on",[198,2159,2160,2164,2169],{},[216,2161,2162],{},[132,2163,698],{},[216,2165,2166],{},[132,2167,2168],{},"quota_exceeded",[216,2170,2171],{},"the balance is used up",[198,2173,2174,2178,2182],{},[216,2175,2176],{},[132,2177,698],{},[216,2179,2180],{},[132,2181,1858],{},[216,2183,2104,2184,2186],{},[132,2185,1821],{}," key used the sandbox's 10,000 calls of the month",[198,2188,2189,2194,2199],{},[216,2190,2191],{},[132,2192,2193],{},"502",[216,2195,2196],{},[132,2197,2198],{},"fraud_unavailable",[216,2200,2201],{},"your instance did not answer: retry in a few seconds",[198,2203,2204,2208,2212],{},[216,2205,2206],{},[132,2207,1868],{},[216,2209,2210],{},[132,2211,1871],{},[216,2213,2214,2215],{},"your instance was paused and is starting: retry after ",[132,2216,2217],{},"Retry-After",[198,2219,2220,2224,2229],{},[216,2221,2222],{},[132,2223,1868],{},[216,2225,2226],{},[132,2227,2228],{},"sandbox_starting",[216,2230,2104,2231,2233,2234],{},[132,2232,1821],{}," key was made a moment ago and the sandbox is not set up yet: retry after ",[132,2235,2217],{},[2237,2238,2239],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":272,"searchDepth":307,"depth":307,"links":2241},[2242,2243,2244,2245,2246,2247,2248,2249,2250,2253,2254,2255,2256,2257,2258],{"id":174,"depth":307,"text":175},{"id":258,"depth":307,"text":259},{"id":862,"depth":307,"text":863},{"id":988,"depth":307,"text":989},{"id":1002,"depth":307,"text":1003},{"id":796,"depth":307,"text":1100},{"id":1206,"depth":307,"text":1207},{"id":1257,"depth":307,"text":1258},{"id":1338,"depth":307,"text":1339,"children":2251},[2252],{"id":1358,"depth":325,"text":1359},{"id":1461,"depth":307,"text":1462},{"id":1649,"depth":307,"text":1350},{"id":1706,"depth":307,"text":1707},{"id":850,"depth":307,"text":1811},{"id":2054,"depth":307,"text":2055},{"id":2071,"depth":307,"text":2072},"Score sign-ups, logins and payments with \u002Ffraud\u002Fv1\u002Fdecide, report events with \u002Ffraud\u002Fv1\u002Fevents, and get a webhook when a case opens.","md",null,{},{"title":2264,"description":2265},"Fraud prevention API: \u002Ffraud\u002Fv1\u002Fdecide","Decide on a sign-up, a login or a payment before you act, with your own openfraud instance. Rules in shadow first, pseudonymized data.","ID1AKiUoQ-3c015ddMsJcbcuKY1vd-7xBsSLrf9xeBg",[2268,2270],{"title":95,"path":96,"stem":97,"description":2269,"children":-1},"Every endpoint of the moderation API in one table, the fraud prevention routes, and the OpenAPI document.",{"title":103,"path":104,"stem":105,"description":2271,"children":-1},"Add the device script to your pages, send its token with each sensitive event, and report the outcome of a step-up challenge.",1792938462798]