API Reference
The Aveiro AML API lets you screen transactions, check sanctions lists, detect fraud signals, and receive real-time webhook alerts — all through a single JSON REST API.
Base URL
risk-api.migrapay.com
Protocol
HTTPS only
Auth header
x-api-key
Make your first request
curl -X POST https://risk-api.migrapay.com/v2/events \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"user_id": "usr_123", "email": "user@example.com", "country": "CA"}'{
"status": 200,
"data": {
"check_id": "chk_01JXXXXXXXXXXXXXXX",
"state": "APPROVE",
"fraud_score": 12,
"risk_level": "LOW",
"created_at": "2026-05-18T10:23:41.000Z"
}
}Authentication
Every request must include your API key in the x-api-key request header. Keys are scoped to your tenant and can be live or sandbox.
Never expose your API key in client-side or frontend code. All calls to the Aveiro API must originate from your server. Use environment variables to store keys securely.
POST /v2/events HTTP/1.1
Host: risk-api.migrapay.com
Content-Type: application/json
x-api-key: mrsk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxKey types
mrsk_live_…Live key
Processes real data. Counts against your plan quota.
mrsk_sandbox_…Sandbox key
Test key. Returns synthetic results, does not count toward quota.
Rate limits
Requests are rate-limited per API key. Exceeding the limit returns HTTP 429. Retry after the number of seconds in the Retry-After header.
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1716028800Idempotency
Pass an Idempotency-Key header (UUID v4) on POST /v2/events to safely retry without creating duplicate checks. Responses are cached for 24 hours.
/v2/eventsScreen a transaction
The primary endpoint. Runs velocity checks, IP intelligence, email risk, device fingerprinting, and AML sanctions screening in a single synchronous call. Completes in under 200 ms on average.
Request body
user_idrequiredYour stable user identifier. Used for velocity, history, and risk trending across checks.
emailUser email. Scored for disposable domain, breach history, and deliverability.
nameFull legal name. Triggers sanctions and PEP list matching when provided.
amountTransaction amount in the smallest currency unit (cents, pence, etc.).
currencyISO 4217 currency code — e.g. CAD, USD, GBP.
countryISO 3166-1 alpha-2 country of the transaction origin. Used for geo-risk and sanctions jurisdiction checks.
ipUser IP address (IPv4 or IPv6). Scored for proxy, VPN, and Tor exit-node usage.
phoneE.164 format phone — e.g. +14165550100. Carrier intelligence and line-type scoring.
metadataArbitrary key-value pairs (max 50 keys). Stored with the check for reference.
import fetch from 'node-fetch'; // or built-in fetch (Node 18+)
const response = await fetch('https://risk-api.migrapay.com/v2/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.MIGRAPAY_API_KEY,
'Idempotency-Key': crypto.randomUUID(), // prevents duplicate processing
},
body: JSON.stringify({
user_id: 'usr_01JXXXXXXX',
email: 'jane.doe@example.com',
name: 'Jane Doe',
amount: 4500,
currency: 'CAD',
country: 'CA',
ip: '203.0.113.42',
}),
});
const { data } = await response.json();
// data.state → 'APPROVE' | 'REVIEW' | 'DECLINE'
// data.fraud_score → 0–100Response — 200 OK
{
"status": 200,
"data": {
"check_id": "chk_01JXXXXXXXXXXXXXXX",
"state": "APPROVE",
"fraud_score": 14,
"risk_level": "LOW",
"signals": {
"ip_proxy": false,
"ip_tor": false,
"velocity_breach": false,
"email_disposable": false,
"email_breached": false,
"sanctions_hit": false,
"pep_match": false,
"country_high_risk": false
},
"created_at": "2026-05-18T10:23:41.000Z"
}
}state values
APPROVERisk score below your configured threshold. Safe to proceed.REVIEWElevated signals detected. Manual review or step-up auth recommended.DECLINEHigh-risk signals or sanctions hit. Block the transaction./v2/eventsList checks
Returns a paginated, cursor-based list of screening checks for your tenant, ordered by most recent first.
Query parameters
limitResults per page. Default 20, max 100.
cursorPagination cursor from the previous response's next_cursor.
stateFilter by decision — APPROVE | REVIEW | DECLINE.
user_idReturn only checks for a specific user identifier.
fromISO 8601 datetime — filter checks created after this timestamp.
toISO 8601 datetime — filter checks created before this timestamp.
{
"status": 200,
"data": {
"checks": [
{
"check_id": "chk_01JXXXXXXXXXXXXXXX",
"user_id": "usr_01JXXXXXXX",
"state": "APPROVE",
"fraud_score": 14,
"created_at": "2026-05-18T10:23:41.000Z"
}
],
"pagination": {
"total": 1482,
"has_more": true,
"next_cursor": "Y3Vyc29yX01UY3dNakl3TWpBd01RPT0="
}
}
}/v2/events/:check_idGet a check
Retrieve the full result of a single screening check by its check_id, including all signals and metadata.
curl https://risk-api.migrapay.com/v2/events/chk_01JXXXXXXXXXXXXXXX \
-H "x-api-key: mrsk_live_••••••••••••••••"{
"status": 200,
"data": {
"check_id": "chk_01JXXXXXXXXXXXXXXX",
"user_id": "usr_01JXXXXXXX",
"email": "jane.doe@example.com",
"state": "REVIEW",
"fraud_score": 62,
"risk_level": "MEDIUM",
"signals": {
"ip_proxy": true,
"ip_tor": false,
"velocity_breach": true,
"email_disposable": false,
"sanctions_hit": false,
"pep_match": false
},
"ip": "203.0.113.42",
"country": "CA",
"metadata": { "order_id": "ord_9876" },
"created_at": "2026-05-18T10:23:41.000Z"
}
}/v1/aml/checkAML / Sanctions screening
Dedicated name-based AML screening against OFAC SDN, UN Consolidated, EU Consolidated, HMT, DFAT, and 200+ global sanctions and watch lists. Also matches against PEP databases and adverse media sources.
Request body
namerequiredFull legal name of the individual or entity to screen.
countryrequiredISO 3166-1 alpha-2 country code. Narrows jurisdictional matching.
user_idYour internal reference for the subject.
dobDate of birth in YYYY-MM-DD format. Significantly improves match precision.
entity_typeindividual (default) or entity for corporate/organisation screening.
const response = await fetch('https://risk-api.migrapay.com/v1/aml/check', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.MIGRAPAY_API_KEY,
},
body: JSON.stringify({
name: 'Jane Doe',
country: 'CA',
user_id: 'usr_01JXXXXXXX',
dob: '1985-03-22',
entity_type: 'individual',
}),
});
const { data } = await response.json();
// data.sanctions_hit → boolean
// data.pep_match → boolean
// data.matches → array of match objectsResponse — 200 OK
{
"status": 200,
"data": {
"screening_id": "aml_01JXXXXXXXXXXXXXXX",
"sanctions_hit": false,
"pep_match": false,
"adverse_media": false,
"risk_score": 8,
"matches": [],
"lists_checked": [
"OFAC_SDN", "UN_CONSOLIDATED", "EU_CONSOLIDATED", "HMT", "DFAT"
],
"screened_at": "2026-05-18T10:23:41.000Z"
}
}Match object
{
"list": "OFAC_SDN",
"name": "JANE DOE",
"score": 0.95,
"dob": "1985-03-22",
"country": "CA",
"categories": ["sanctions", "terrorism"]
}/v1/crypto/screenCrypto address screening
Screen a cryptocurrency wallet address for exposure to illicit activity, OFAC-sanctioned entities, darknet markets, mixers, and high-risk exchanges.
Request body
addressrequiredBlockchain wallet address to screen.
currencyrequiredCryptocurrency ticker — BTC, ETH, USDT, etc.
user_idYour internal reference for the wallet owner.
const response = await fetch('https://risk-api.migrapay.com/v1/crypto/screen', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.MIGRAPAY_API_KEY,
},
body: JSON.stringify({
address: '1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf',
currency: 'BTC',
user_id: 'usr_01JXXXXXXX',
}),
});
const { data } = await response.json();Response — 200 OK
{
"status": 200,
"data": {
"address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf",
"currency": "BTC",
"risk_score": 5,
"risk_level": "LOW",
"sanctions_hit": false,
"exposures": {
"darknet": 0,
"mixer": 0,
"exchange": 0,
"gambling": 0
},
"screened_at": "2026-05-18T10:23:41.000Z"
}
}Webhooks
Register HTTPS endpoints to receive real-time event notifications. Aveiro retries failed deliveries with exponential backoff (1s → 5m → 30m → 2h → 12h) for up to 24 hours.
/v1/webhooksList all webhook endpoints./v1/webhooksRegister a new endpoint./v1/webhooks/:idUpdate URL or subscribed events./v1/webhooks/:idDelete a webhook endpoint./v1/webhooks/deliveriesList recent delivery attempts.Create webhook — request body
urlrequiredYour HTTPS endpoint URL. Must return 2xx within 10 seconds.
eventsrequiredArray of event type strings to subscribe to.
const response = await fetch('https://risk-api.migrapay.com/v1/webhooks', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.MIGRAPAY_API_KEY,
},
body: JSON.stringify({
url: 'https://yourapp.com/webhooks/aml',
events: ['fraud.check.completed', 'aml.sanctions_hit'],
}),
});
const { data } = await response.json();
// Store data.id — you'll need it to update or deleteEvent types
fraud.check.completedA /v2/events screening check finished.aml.sanctions_hitA sanctions list match was found.aml.pep_matchA Politically Exposed Person match was found.rule.threshold_breachedA custom rule threshold was exceeded.case.createdA new compliance case was opened.case.escalatedA case was escalated to senior review.Signature verification
Every delivery includes an X-Migrapay-Signature header containing an HMAC-SHA256 signature of the raw request body. Always verify this before processing the event.
import crypto from 'crypto';
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature.replace('sha256=', '')),
);
}
// In your Express/Next.js handler:
app.post('/webhooks/aml', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-migrapay-signature'] as string;
if (!verifyWebhook(req.body.toString(), sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body.toString());
// handle event.type ...
res.sendStatus(200);
});Errors & status codes
All errors return a consistent JSON body with a status code and a human-readable message. Never rely on HTTP status alone — always check the message field for actionable detail.
200Success. The request was processed and a result returned.400Bad Request. A required parameter is missing or invalid.401Unauthorized. The x-api-key header is missing or invalid.402Payment Required. Your plan quota has been exhausted.409Conflict. Duplicate Idempotency-Key with different request body.429Too Many Requests. Rate limit exceeded. See Retry-After header.500Internal Server Error. Contact support if this persists.{
"status": 400,
"message": "Validation error: user_id is required"
}