API Documentation

Base URL: https://flashloanlab.com/api  ·  All responses are JSON  ·  llms.txt

Overview

The FlashLoanLab API is a JSON REST API served by a Fastify backend. It handles authentication, opportunity discovery, trade execution, auto-trading configuration, and admin management.

All timestamps are ISO 8601 strings in UTC. Chain IDs are integers (e.g. 8453). Token amounts are strings representing the raw value in the token's smallest unit (wei for ETH-based tokens).

Supported chains: Base (8453), Arbitrum One (42161), Ethereum (1), Optimism (10), Polygon (137). Each chain scans Uniswap V3 plus chain-specific DEXes: SushiSwap V3 (Base, Arbitrum, Ethereum), QuickSwap V3 (Polygon), SushiSwap V2 (Arbitrum, Optimism, Polygon), QuickSwap V2 (Polygon), Camelot V2 (Arbitrum), and Uniswap V2 (Ethereum).

Request format

POST /auth/login
Content-Type: application/json
Authorization: Bearer <session_token>   // required on authenticated routes

{
  "email": "user@example.com",
  "password": "hunter2"
}

Response envelope

Successful responses return the data directly. Errors use:

{
  "error": "Invalid credentials",   // human-readable message
  "code":  "UNAUTHORIZED"           // optional machine-readable code
}

Authentication

Sessions are Bearer tokens returned on login or register. Pass the token in the Authorization header on every authenticated request. Tokens do not expire on their own — call POST /auth/logout to invalidate.

POST
/auth/register

Create a new account

POST
/auth/login

Sign in and receive a session token

POST
/auth/logout

Invalidate the current session token

POST
/auth/forgot-password

Send a password reset email (always returns 200)

POST
/auth/reset-password

Set a new password using the emailed token

Register

POST /auth/register
{
  "email":    "alice@example.com",
  "password": "at_least_8_chars",
  "name":     "Alice"             // optional
}

→ 201
{
  "user":  { "id": "...", "email": "alice@example.com", "name": "Alice", "role": "USER", "plan": "FREE" },
  "token": "fll_tok_..."
}

Login

POST /auth/login
{
  "email":    "alice@example.com",
  "password": "at_least_8_chars"
}

→ 200
{
  "user":  { "id": "...", "email": "alice@example.com", "role": "USER", "plan": "FREE" },
  "token": "fll_tok_..."
}

Reset password

// Step 1 — request a reset link
POST /auth/forgot-password
{ "email": "alice@example.com" }
→ 200 { "message": "If that address exists, a reset email has been sent." }

// Step 2 — set new password using token from email link
POST /auth/reset-password
{ "token": "<token_from_email>", "password": "new_password" }
→ 200 { "message": "Password updated successfully." }

Opportunities

Opportunities are arbitrage price discrepancies detected by the scanner. They include a confidence score (0–100), estimated profit, simulation result, and token safety data.

GET
/opportunities

List active opportunities — query params: page, limit, chainId, minScore, maxScore, minProfitPct, status, sort (score|profit|profitPct|updatedAt|createdAt)

GET
/opportunities?history=true

Opportunity history — all expired/executed/rejected opportunities sorted by createdAt desc

GET
/opportunities/:id

Get a single opportunity by ID (includes chain, token, and recent simulations)

POST
/opportunities/:id/simulate

Enqueue a fork simulation for this opportunity → returns simulationId and jobId

PATCH
/opportunities/:id/status

Update status — body: { status: ACTIVE | REJECTED }

Opportunity object

{
  "id":               "opp_...",
  "chainId":          8453,
  "chain":            { "chainId": 8453, "name": "Base", "shortName": "Base" },
  "strategyType":     "DEX_ARBITRAGE",
  "status":           "ACTIVE",
  "borrowToken":      { "address": "0x42...06", "symbol": "WETH", "decimals": 18, "tier": 1 },
  "borrowAmount":     "1000000000000000000",   // wei string
  "borrowAmountUsd":  3400.00,

  // ── Financials (all USD) ───────────────────────────────────────────────────
  "grossProfitUsd":   18.32,   // spread profit; DEX pool fees already deducted
  "flashLoanFeeUsd":   1.70,   // Aave V3 0.05% of borrow
  "gasCostUsd":        2.10,   // estimated fast gas
  "dexFeesUsd":        6.80,   // informational only — already reflected in grossProfitUsd
  "netProfitUsd":     13.22,   // grossProfit − flashLoanFee − gas − slippage reserve
  "profitPct":         0.389,  // netProfitUsd / borrowAmountUsd * 100
  // personalised to caller's plan (requires auth):
  "userProfitUsd":     9.92,   // netProfitUsd × (1 − platformFeePct/100)
  "platformFeeUsd":    3.30,   // netProfitUsd × platformFeePct/100
  "platformFeePct":   25.0,    // caller's plan rate (Free=25, Pro=20, Elite=15, Enterprise=10)

  "score":            92,
  "mevRisk":          "LOW",
  "simulationStatus": "PASSED",
  "isLiveEligible":   true,
  "isAutoEligible":   true,
  "createdAt":        "2025-11-01T12:34:56Z",
  "expiresAt":        "2025-11-01T12:35:26Z"
}

minProfitPct filter

Pass ?minProfitPct=0.05to only return opportunities where net profit is at least 0.05% of the borrow amount. If omitted and the caller is authenticated, the API auto-applies the user's saved minProfitPct from Safety Settings. Example: 0.05% on a $50k borrow = $25 minimum net profit.

Execution

Execution is a two-step process. First, call /execute/:id/prepare to get the transaction parameters for FlashLoanReceiver.executeArbitrage(). Sign and broadcast the transaction yourself (MetaMask / wagmi). Then call /execute/:executionId/receipt with the tx hash so the platform can confirm the settlement on-chain.

POST
/execute/:opportunityId/prepare

Validate and return tx params

POST
/execute/:executionId/receipt

Record tx hash after broadcasting

GET
/execute/history

User's execution history

Prepare response

POST /execute/opp_.../prepare
→ 200
{
  "executionId": "exec_...",
  "contractAddress": "0x...",   // FlashLoanReceiver deployed on this chain
  "params": {
    "pool":         "0x...",    // Aave V3 pool address
    "asset":        "0x...",    // borrow token
    "amount":       "1000000000000000000",
    "buyDex":       "0x...",
    "sellDex":      "0x...",
    "feeBps":       2000,       // platform fee in basis points (20%)
    "deadline":     1730462096
  },
  "estimatedGas": "420000",
  "gasPrice":     "50000000"    // in wei, current fast price
}

Receipt

POST /execute/exec_.../receipt
{ "txHash": "0x..." }
→ 200 { "status": "confirmed", "profit": "3820000000000000" }

Auto Trading

Auto Trading runs a background worker that fires on opportunities scoring ≥90. It requires a trading wallet to be registered. All safety limits are enforced server-side — the bot will pause itself if any threshold is breached.

GET
/auto-trading/settings

Get current settings and safety limits

PATCH
/auto-trading/settings

Update risk thresholds

POST
/auto-trading/arm

Enable auto execution

POST
/auto-trading/disarm

Disable auto execution

POST
/auto-trading/emergency-stop

Immediately halt all activity

GET
/auto-trading/status

Today's trade stats

GET
/auto-trading/logs

Today's activity log

POST
/auto-trading/wallet

Register encrypted trading wallet

DELETE
/auto-trading/wallet

Remove trading wallet

Settings object

{
  "enabled":           false,
  "mode":              "paper",      // "paper" | "mainnet"
  "minScore":          90,           // only fire on opps scoring >= this
  "minProfitUsd":      5,
  "maxDailyLossUsd":   100,
  "maxTradesPerDay":   50,
  "maxFailedTxs":      3,
  "hasWallet":         true,
  "walletAddress":     "0x..."       // derived from stored key, never the key itself
}

Registering a trading wallet

The private key is encrypted with AES-256-GCM server-side before storage. It is never logged, never returned by any API endpoint, and never accessible from the frontend.

POST /auto-trading/wallet
{ "privateKey": "0x..." }
→ 200 { "walletAddress": "0x...", "message": "Wallet registered securely." }

Earnings

The platform deducts a percentage-based fee from each profitable trade, determined by the user's plan. Use these endpoints to inspect fee config, preview profit splits, change plan, and view settlement history.

GET
/earnings/fee-config

Authenticated user's current fee config (plan, feeBps, monthlyFeeUsd)

GET
/earnings/preview?grossProfitUsd=X

Profit split preview for a given gross profit amount

POST
/earnings/plan

Self-service plan change — applies immediately to future trades

GET
/earnings/plan-info

All plan metadata: fee percentages and monthly fees

GET
/earnings/history

Settlement history (paginated)

Plan change

POST /earnings/plan
{ "plan": "PRO" }   // FREE | PRO | ELITE | ENTERPRISE

→ 200
{
  "plan":           "PRO",
  "platformFeePct": 20,
  "monthlyFeeUsd":  0
}

Safety & Logs

Safety controls gate live and auto-trading execution. Audit logs record account activity (logins, settings changes, executions). Risk events capture safety-limit breaches.

GET
/safety/settings

Get the current safety settings

PUT
/safety/settings

Update safety controls (score thresholds, borrow caps, etc.)

POST
/safety/emergency-stop

Activate emergency stop — disables all live and auto execution

GET
/audit-logs

Account activity trail (paginated)

GET
/risk-events

Risk alerts and safety-limit breaches

PATCH
/risk-events/:id/resolve

Mark a risk event as resolved

GET
/email-preferences

Get email notification preferences (executionAlerts, autoTradeAlerts, riskAlerts, emergencyStopAlerts, weeklyDigest, opportunityAlerts)

PUT
/email-preferences

Update email notification preferences — any subset of boolean fields accepted

Safety settings object

{
  "liveExecutionEnabled":      false,
  "minScoreLive":              70,     // min score for manual live execution
  "minScoreAuto":              90,     // min score for auto trading
  "minProfitPct":              0.05,   // min net profit % of borrow to surface opportunities
                                       // (0 = no filter; e.g. 0.05 = $25 on a $50k borrow)
  "maxBorrowUsd":              50000,
  "maxSlippagePct":            1.5,
  "maxGasGwei":                50,
  "maxDailyLossUsd":           500,
  "requireResimulation":       true,
  "requireWalletConfirmation": true,
  "emergencyStopActive":       false
}

Errors & Rate Limits

HTTP status codes

400Bad RequestValidation failed — check the error message for the field
401UnauthorizedMissing or invalid Bearer token
403ForbiddenToken valid but insufficient role/plan for this action
404Not FoundResource does not exist or you do not have access
409ConflictDuplicate — e.g. email already registered
422UnprocessableBusiness logic error — e.g. opportunity expired
429Too Many RequestsRate limit hit — back off and retry after the Retry-After header
500Server ErrorUnexpected error — please report with the request ID

Rate limits

The API is rate-limited per IP: 100 requests per minute for most routes, 10 requests per minute for auth endpoints. Exceeding the limit returns 429 with a Retry-After header.

Machine-readable reference

An LLM-optimised version of this documentation is available at /llms.txt.