REST API · v2.0

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

bash
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"}'
json
{
  "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.

http
POST /v2/events HTTP/1.1
Host: risk-api.migrapay.com
Content-Type: application/json
x-api-key: mrsk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Key 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.

PlanRequests / minBurst
Starter6010
Growth50050
EnterpriseCustomCustom
http
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1716028800

Idempotency

Pass an Idempotency-Key header (UUID v4) on POST /v2/events to safely retry without creating duplicate checks. Responses are cached for 24 hours.

POST/v2/events

Screen 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_idrequired
string

Your stable user identifier. Used for velocity, history, and risk trending across checks.

email
string

User email. Scored for disposable domain, breach history, and deliverability.

name
string

Full legal name. Triggers sanctions and PEP list matching when provided.

amount
integer

Transaction amount in the smallest currency unit (cents, pence, etc.).

currency
string

ISO 4217 currency code — e.g. CAD, USD, GBP.

country
string

ISO 3166-1 alpha-2 country of the transaction origin. Used for geo-risk and sanctions jurisdiction checks.

ip
string

User IP address (IPv4 or IPv6). Scored for proxy, VPN, and Tor exit-node usage.

phone
string

E.164 format phone — e.g. +14165550100. Carrier intelligence and line-type scoring.

metadata
object

Arbitrary key-value pairs (max 50 keys). Stored with the check for reference.

node
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–100

Response — 200 OK

json
{
  "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.
GET/v2/events

List checks

Returns a paginated, cursor-based list of screening checks for your tenant, ordered by most recent first.

Query parameters

limit
integer

Results per page. Default 20, max 100.

cursor
string

Pagination cursor from the previous response's next_cursor.

state
string

Filter by decision — APPROVE | REVIEW | DECLINE.

user_id
string

Return only checks for a specific user identifier.

from
string

ISO 8601 datetime — filter checks created after this timestamp.

to
string

ISO 8601 datetime — filter checks created before this timestamp.

json
{
  "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="
    }
  }
}
GET/v2/events/:check_id

Get a check

Retrieve the full result of a single screening check by its check_id, including all signals and metadata.

bash
curl https://risk-api.migrapay.com/v2/events/chk_01JXXXXXXXXXXXXXXX \
  -H "x-api-key: mrsk_live_••••••••••••••••"
json
{
  "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"
  }
}
POST/v1/aml/check

AML / 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.

OFAC SDNUN ConsolidatedEU ConsolidatedHMTDFAT200+ lists

Request body

namerequired
string

Full legal name of the individual or entity to screen.

countryrequired
string

ISO 3166-1 alpha-2 country code. Narrows jurisdictional matching.

user_id
string

Your internal reference for the subject.

dob
string

Date of birth in YYYY-MM-DD format. Significantly improves match precision.

entity_type
string

individual (default) or entity for corporate/organisation screening.

node
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 objects

Response — 200 OK

json
{
  "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

json
{
  "list":       "OFAC_SDN",
  "name":       "JANE DOE",
  "score":      0.95,
  "dob":        "1985-03-22",
  "country":    "CA",
  "categories": ["sanctions", "terrorism"]
}
POST/v1/crypto/screen

Crypto address screening

Screen a cryptocurrency wallet address for exposure to illicit activity, OFAC-sanctioned entities, darknet markets, mixers, and high-risk exchanges.

Request body

addressrequired
string

Blockchain wallet address to screen.

currencyrequired
string

Cryptocurrency ticker — BTC, ETH, USDT, etc.

user_id
string

Your internal reference for the wallet owner.

node
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

json
{
  "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.

GET/v1/webhooksList all webhook endpoints.
POST/v1/webhooksRegister a new endpoint.
PATCH/v1/webhooks/:idUpdate URL or subscribed events.
DELETE/v1/webhooks/:idDelete a webhook endpoint.
GET/v1/webhooks/deliveriesList recent delivery attempts.

Create webhook — request body

urlrequired
string

Your HTTPS endpoint URL. Must return 2xx within 10 seconds.

eventsrequired
string[]

Array of event type strings to subscribe to.

node
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 delete

Event 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.

typescript
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.

StatusMeaning
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.
json
{
  "status":  400,
  "message": "Validation error: user_id is required"
}