Risk & fraud
Fraud scoring, sanctions (OFAC) screening, device/IP fingerprinting and identity verification (KYC) behind one risk API.
1. Overview
https://api.infrai.cc/v1/riskAuthorization: Bearer $INFRAI_API_KEY# Call any /v1/risk capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/risk/... \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json"2. Methods (3)
2.1risk.score
Score a user/account event (login, payment, signup) for fraud and abuse risk, returning a normalized 0..1 score plus an accept / review / reject disposition. Billable work-action, ML high-margin (service_markup).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
subject_id | string | Optional | User / account id under evaluation. |
event_type | string | Optional | The event being scored / reported.default: "login"e.g. login |
ip | string | Optional | Originating IP address.format: ipv4 |
email | string | Optional | Email address associated with the subject.format: email |
device_fingerprint | string | Optional | Device fingerprint / visitor id. |
amount | number | Optional | Transaction amount.≥ 0 |
currency | string | Optional | ISO currency code for the amount.3–3 chars |
properties | Record<string, unknown> | Optional | Arbitrary signal properties. |
vendor | "maxmind" | "sift" | "shumei" | "tongdun" | Optional | Explicit vendor pin. |
idempotency_key | string | Optional | Client-supplied key to make the call idempotent. |
Returns
RiskScore { score, decision, reasons: string[] }| Name | Type | Description |
|---|---|---|
vendor | string | Vendor that handled or will handle this request |
score | number | normalized risk score, higher = riskier0–1 |
disposition | "accept" | "review" | "reject" | Risk assessment disposition (allow, challenge, deny) |
score_id | string | Unique identifier for this risk score |
reasons | string[] | List of reasons contributing to the risk score |
Example
One-time prep (each example is assumed to be complete):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/risk/score \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/risk/score",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/risk/score",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/risk/score",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/risk/score", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/risk/score"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/risk/score");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/risk/score");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/risk/score")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/risk/score")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.2risk.device.fingerprint
Resolve a stable device fingerprint / visitor id from a client-collected token plus IP and user-agent signals, for bot and incognito detection. Served by a vendor (sift / castle).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
request_token | string | Optional | Client-collected token / visitor id. |
ip | string | Optional | Originating IP address. |
user_agent | string | Optional | Client user-agent string. |
properties | Record<string, unknown> | Optional | Arbitrary signal properties. |
Returns
Device { device_id, signals: object }| Name | Type | Description |
|---|---|---|
ok | boolean | Whether the fingerprint was processed |
fingerprint_hash | string | null | Hash of the device fingerprint |
risk_score | number | null | Risk score for this device (0-1) |
Example
One-time prep (each example is assumed to be complete):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/risk/device/fingerprint \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/risk/device/fingerprint",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/risk/device/fingerprint",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/risk/device/fingerprint",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/risk/device/fingerprint", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/risk/device/fingerprint"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/risk/device/fingerprint");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/risk/device/fingerprint");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/risk/device/fingerprint")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/risk/device/fingerprint")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.3risk.event.report
Report a risk-relevant event or label (chargeback, fraud, abuse) back to the vendor as feedback to improve future scoring.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
subject_id | string | Optional | User / account id under evaluation. |
event_type | string | Required | The event being scored / reported.e.g. chargeback |
label | "fraud" | "not_fraud" | Optional | Outcome label — fraud, legit or chargeback. |
reason | string | Optional | Free-text reason for the report. |
properties | Record<string, unknown> | Optional | Arbitrary signal properties. |
Returns
{ ok: boolean }| Name | Type | Description |
|---|---|---|
ok | boolean | Whether the event was recorded |
event_id | string | null | Unique identifier for the recorded event |
Example
One-time prep (each example is assumed to be complete):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/risk/event/report \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"event_type": "sample"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/risk/event/report",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'event_type': 'sample'},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/risk/event/report",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"event_type": "sample"}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/risk/event/report",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"event_type": "sample"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{"event_type": "sample"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/risk/event/report", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/risk/event/report"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"event_type\": \"sample\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/risk/event/report");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"event_type\": \"sample\"}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/risk/event/report");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"event_type\": \"sample\"}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/risk/event/report")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"event_type": "sample"}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/risk/event/report")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"event_type": "sample"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}Advanced: pin a vendor
By default infrai routes each call to the best available provider — you do not pick a vendor. As an escape hatch, this capability accepts an optional vendor parameter to pin one specific provider. Every live vendor for this capability is available in real time from the discovery endpoint for the capability id — see the discovery API.
GET /v1/discovery/{capability}risk.score
3. All capabilities
Every routed capability in this module — the complete public REST contract. The methods above are the guided walkthrough; this index is the full reference.
risk.device.fingerprintPOST /v1/risk/device/fingerprintResolve a stable device fingerprint / visitor id from a client-collected token plus IP and user-agent signals, for bot and incognito detection. Served by a vendor (sift).
Parameters (4)
| Name | Type | Required | Description |
|---|---|---|---|
request_token | string | Optional | client-collected token / visitor id |
ip | string | Optional | IP address from which the session was created |
user_agent | string | Optional | User-Agent string of the client |
properties | object | Optional | Additional properties for risk assessment |
risk.event.reportPOST /v1/risk/event/reportReport a risk-relevant event or label (chargeback, fraud, abuse) back to the vendor as feedback to improve future scoring.
Parameters (5)
| Name | Type | Required | Description |
|---|---|---|---|
subject_id | string | Optional | Identifier of the subject being risk-scored |
event_type | string | Required | Type of risk event (e.g. login, payment, registration)e.g. chargeback |
label | "fraud" | "not_fraud" | Optional | Risk label (e.g. low, medium, high) |
reason | string | Optional | Reason for the current state or action |
properties | object | Optional | Additional properties for risk assessment |
risk.scorePOST /v1/risk/scoreScore a user/account event (login, payment, signup) for fraud and abuse risk, returning a normalized 0..1 score plus an accept / review / reject disposition. Billable work-action, ML high-margin (service_markup).
Parameters (10)
| Name | Type | Required | Description |
|---|---|---|---|
subject_id | string | Optional | user/account id under evaluation |
event_type | string | Optional | Type of risk event (e.g. login, payment, registration)default: "login"e.g. login |
ip | string | Optional | IP address from which the session was createdformat: ipv4 |
email | string | Optional | Email addressformat: email |
device_fingerprint | string | Optional | Device fingerprint hash for identity tracking |
amount | number | Optional | Monetary amount in the specified currency≥ 0 |
currency | string | Optional | ISO 4217 currency code (e.g. USD, CNY)3–3 chars |
properties | object | Optional | Additional properties for risk assessment |
vendor | "maxmind" | "sift" | "shumei" | "tongdun" | Optional | Vendor that handled or will handle this request |
idempotency_key | string | Optional | Client-provided idempotency key; prevents duplicate execution on retry |
4. End-to-end example
A production-style walkthrough of this module: configure once, then run the flow. It exercises most of the module's APIs.
One-time prep (each example is assumed to be complete):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."# 1) Auth: every call is a raw HTTPS request to the Infrai gateway carrying
# only your project key. No SDK, no install.
# Get your key: sign in with Google/GitHub at https://infrai.cc/login for a
# project key + $2 free credit (email sign-in starts at $0). On 402
# INSUFFICIENT_CREDIT, add funds at https://infrai.cc/billing (or POST
# /v1/account/topup and open the returned checkout_url).
export INFRAI_API_KEY="ifr_..." # from https://infrai.cc/login
# 1) Auth: every call is a raw HTTPS request carrying only your project key.
# No SDK to install — just the `requests` library.
import os, requests
BASE = "https://api.infrai.cc"
HEADERS = {
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
"Content-Type": "application/json",
}
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch().
const BASE = "https://api.infrai.cc";
const HEADERS = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch(), typed.
const BASE = "https://api.infrai.cc";
const HEADERS: Record<string, string> = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
5. Developer guides
Move from endpoint details to complete workflows, production patterns and troubleshooting guides verified against the live API.
Risk & fraud developer guides