API Reference
MCP tools, TypeScript SDK, and REST endpoints for Lu71.
MCP Setup
Fastest path. One command gives any MCP-compatible agent dispute tools.
shellnpx lu71-install --key=lu71_live_YOUR_KEYYour agent gets these tools:
lu71_capture_intentCall BEFORE every purchase. Returns a signed receipt (intentId + signature) required for disputes.
lu71_file_disputeFile a chargeback. Requires intentId + signature from capture_intent, plus the transaction ID from Stripe, Lithic, Visa, or Mastercard.
lu71_check_disputeGet dispute status: submitted, under_review, won (money back), or lost (no charge).
lu71_list_disputesList all disputes with status, amount, reason, platform, and dates.
lu71_connect_statusCheck which card platforms are connected and their connection method.
lu71_account_statusDiagnose setup issues: 2FA status, active API keys, connected platforms.
lu71_verify_paymentCheck a crypto address for scams, sanctions, and fraud before sending. Supports Ethereum, Solana, Bitcoin, XRP, and 6 more chains. Returns risk score + recommendation.
lu71_update_disputeAdd evidence, notes, or communication records to an existing dispute.
Manual config (Claude Desktop):
json{
"mcpServers": {
"lu71": {
"command": "npx",
"args": ["-y", "@lu71/mcp", "--key=lu71_live_YOUR_KEY"]
}
}
}Remote HTTP (no local install needed):
json{
"mcpServers": {
"lu71": {
"url": "https://api.getlu71.com/mcp",
"headers": { "x-api-key": "lu71_live_YOUR_KEY" }
}
}
}TypeScript SDK
Any package manager:
shellnpm install @lu71/sdk
# or
pnpm add @lu71/sdk
# or
bun add @lu71/sdkQuick start:
typescriptimport { Lu71 } from "@lu71/sdk"
const lu71 = new Lu71({ apiKey: "lu71_live_..." })
// 1. Capture intent before purchase
const { intentId, signature } = await lu71.captureIntent({
description: "Buy 100 blue widgets",
merchant: "WidgetCo",
maxAmount: 5000,
})
// 2. Agent makes purchase with its card...
// 3. File dispute when something goes wrong
const dispute = await lu71.fileDispute({
intentId,
intentSignature: signature,
transactionId: "ipi_xxx",
reason: "not_as_described",
description: "Received red widgets instead of blue",
})REST Endpoints
All requests require an x-api-key header except signup. Click to expand.
Creates a customer account. Returns an API key for authentication. After signup, enable 2FA and add a payment method to generate production keys.
Request
json{
"name": "Acme Corp",
"email": "[email protected]",
"password": "min6chars"
}Response
json{
"message": "Account created.",
"customerId": "cus_abc123",
"apiKey": "lu71_live_..."
}Call this BEFORE every purchase your agent makes. It creates a cryptographically signed record of what the agent plans to buy. The returned intentId and signature are required when filing a dispute later. Without them, disputes will be rejected.
Request
json{
"description": "Buy 100 blue widgets from WidgetCo",
"merchant": "WidgetCo",
"maxAmount": 5000,
"currency": "gbp",
"constraints": { "color": "blue", "quantity": "100" }
}Response
json{
"message": "Purchase intent captured.",
"intentId": "int_abc123",
"signature": "hmac_sha256_...",
"createdAt": "2026-06-05T10:00:00Z"
}File a chargeback when a purchase goes wrong. You must provide the intentId and signature from a previous capture_intent call, plus the transaction ID from your card platform (Stripe, Lithic, Visa, or Mastercard). The description becomes part of the evidence submitted to the card network, so be factual and specific.
Request
json{
"intentId": "int_abc123",
"intentSignature": "hmac_sha256_...",
"transactionId": "ipi_xxx",
"reason": "not_as_described",
"description": "Received red widgets instead of blue",
"evidence": {
"whatWasReceived": "100 red widgets",
"productType": "merchandise",
"receivedAt": "2026-06-06T14:00:00Z",
"returnStatus": "merchant_rejected"
}
}Response
json{
"message": "Dispute filed.",
"disputeId": "dsp_abc123",
"status": "submitted",
"platformDisputeId": "idp_xxx"
}Returns the full details of a single dispute including status, evidence, platform info, and resolution dates.
Response
json{
"id": "dsp_abc123",
"status": "won",
"amount": 5000,
"currency": "gbp",
"reason": "not_as_described",
"platform": "stripe",
"transactionId": "ipi_xxx",
"description": "Received red widgets instead of blue",
"filedAt": "2026-06-05T10:30:00Z",
"resolvedAt": "2026-06-20T09:00:00Z"
}Returns all disputes for the authenticated account, ordered by most recent. Each dispute includes full details.
Response
json[
{ "id": "dsp_abc123", "status": "won", "amount": 5000, ... },
{ "id": "dsp_def456", "status": "submitted", "amount": 2000, ... }
]Returns a URL to redirect your user to Stripe's OAuth consent screen. After authorization, Stripe redirects back and we store the connected account ID. We never store your Stripe API key.
Response
json{
"url": "https://connect.stripe.com/oauth/authorize?...",
"message": "Redirect customer to this URL"
}Connect a Lithic account using a restricted API key. The key should have disputes:write scope. We validate it against Lithic's API before storing.
Request
json{ "apiKey": "li_restricted_..." }Response
json{ "message": "Lithic connected. Using restricted API key." }Connect Visa Intelligent Commerce using your API key and shared secret from developer.visa.com.
Request
json{ "apiKey": "visa_...", "sharedSecret": "..." }Response
json{ "message": "Visa connected. Using API key and shared secret." }Connect Mastercard Agent Pay using your consumer key and signing key (PEM) from developer.mastercard.com.
Request
json{ "consumerKey": "mc_...", "signingKey": "-----BEGIN PRIVATE KEY-----..." }Response
json{ "message": "Mastercard connected. Using consumer key and signing key." }Register a URL where we will POST dispute status updates. Returns a signing secret you can use to verify that incoming webhooks are genuinely from Lu71.
Request
json{ "url": "https://your-app.com/webhooks/lu71" }Response
json{
"message": "Webhook configured.",
"webhookUrl": "https://your-app.com/webhooks/lu71",
"webhookSecret": "whsec_...",
"events": ["dispute.submitted", "dispute.under_review", "dispute.won", "dispute.lost"]
}Check a blockchain address for scams, sanctions, and fraud risk before sending payment. Supports 10 chains. Returns a risk score (0-100), risk level, flags, and a recommendation (SAFE / CAUTION / DO NOT PAY). Crypto payments are irreversible — always verify first.
Request
json{ "recipient": "0x098B716B8Aaf21512996dC57EB0615e2383E2f96", "chain": "ethereum" }Response
json{
"riskScore": 100,
"riskLevel": "critical",
"flags": ["blacklisted", "stealing_attack", "sanctioned"],
"recommendation": "DO NOT PAY",
"sources": ["goplus"],
"chain": "ethereum",
"address": "0x098B716B..."
}Dispute Reasons
Use one of these reason codes when filing:
not_receivedItem was paid for but never arrivednot_as_describedItem received does not match what was orderedduplicateCharged more than once for the same purchaseunauthorizedCharge was not authorized by the cardholdercancelledOrder was cancelled but payment was still takenservice_not_renderedService was paid for but never providedotherDoes not fit the above categoriesWebhook Events
Register a URL via POST /v1/connect/webhooks. We POST on every status change. Each payload is HMAC-signed.
json{
"id": "evt_1717578600000",
"type": "dispute.won",
"created": "2026-07-02T09:30:00Z",
"data": {
"disputeId": "dsp_abc123",
"status": "won",
"amount": 5000,
"currency": "gbp",
"reason": "not_as_described",
"resolvedAt": "2026-07-02T09:30:00Z"
}
}Available events:
dispute.submittedDispute has been filed with the card network. Evidence submitted.
dispute.under_reviewCard network is actively reviewing the evidence. Typically takes 1 to 4 weeks.
dispute.wonDispute resolved in your favour. Funds returned to cardholder. Success fee charged.
dispute.lostDispute resolved in the merchant's favour. No fee charged.
Verify webhook signatures:
typescriptimport crypto from "crypto"
function verifyWebhook(body: string, signature: string, secret: string): boolean {
const expected = crypto.createHmac("sha256", secret).update(body).digest("hex")
return signature === expected
}
// In your webhook handler:
const sig = req.headers["x-lu71-signature"]
const valid = verifyWebhook(req.body, sig, "whsec_your_secret")
if (!valid) return res.status(401).send("Invalid signature")