Getting Started
Integration Guide

Integration Guide

This page puts the pieces together. Each step has its own detailed page; what matters here is the order.

Generate and register your key

Generate an Ed25519 key pair, register the public key from the panel, take the kid. The private key stays on your server.

→ Quickstart

Write the token layer

Put it in one place in your application: a module that builds the canonical string, signs it, mints the token and holds it in cache. Every other call asks that module for a token.

Get this right once and it works for every product — the authentication layer is shared.

⚠️

This is where first integrations most often get stuck. On a bodyless request you must not add the Digest: line to the canonical string, and the first argument to crypto.sign must be null. → Authentication

Wire up browser telemetry (optional)

If you want device and behavioural signals, add the Identity Web SDK to your page. It is headless — there is no widget to mount.

<script src="https://cdn.lunixi.com/lunixi-identity.min.js"></script>
const client = await Lunixi.identity.init({
  sessionBootstrapUrl: '/lunixi/identity/session',
  subjectId: 'cus_8f2a9c',
  productContext: 'checkout',
});
const snapshot = await client.analyze();

sessionBootstrapUrl is an endpoint on your server, where you mint the session token. Your secret key never reaches the page.

🚫

The SDK is not fail-open: if init(), analyze() or track() fails it throws — it does not silently return a pass. You own the fallback.

→ Identity Web SDK

Ask for the decision at the right moment

Request the fraud decision before you capture the money. Send whatever context you have — the engine reads only the fields your active rules reference.

POST /api/v1/fraud/decisions/evaluate

Act on what comes back:

DecisionWhat you do
allowProceed with the payment
force_3dStep up to 3DS
reviewHold for review; do not capture
blockDecline

→ Decision API

Feed events for history-based rules

Rules like velocity and baseline deviation cannot work from a single transaction. "This customer made 12 transactions in the last 24 hours" comes from the event backbone:

POST /api/v1/fraud/events/transactions        (single)
POST /api/v1/fraud/events/transactions/batch  (batch)
⚠️

These endpoints are Ed25519 signed, not Bearer. Without an event feed, most of the ready-made templates never fire.

Keep the trace

Write the requestId from every decision response, and the reasoning behind the decision (code, reasonCodes, flowPath), into your own records. These are what get looked up in a dispute, an audit or a support request.

Set up webhooks

Create your endpoint, put the signing secret in your vault, write the verification. In the first version it has one job: verify the signature → write to your queue → return 2xx.

→ Webhook Setup

Publish your flow

🚫

Do not go live without publishing rules. An unconfigured merchant does not get allow — you get the policy default (typically review) with code fraud.decision.unconfigured, and all of your traffic lands in review.

→ Flows and Resolution

Go-live checklist

  • Private key in a secrets manager, not in the repo or the image
  • Token is cached, not minted per call
  • The Authorization header is not logged
  • Error branching goes through code, not message
  • requestId is written to your own logs
  • Amounts are sent as minor-unit integers
  • Idempotency-Key on create-payment is derived from your transaction
  • Webhook signature is verified and consumption is idempotent on x-lunixi-event-id
  • You have decided what happens when we are unreachable (fail-open / fail-closed / queue)
  • The fraud flow is published and has been watched in shadow mode
  • force_3d genuinely steps the transaction up to 3DS

Related