API Endpoints

Complete reference for all ILAL API endpoints.

Base URL
https://ilal-mvp-production.up.railway.app/api/v1
Authorization: Bearer TOKENJWT (frontend)
X-API-Key: YOUR_KEYAPI Key (server-to-server)
Rate Limits (per minute, per API key)
FREE
60 req/min
1,000 req/month
PRO
300 req/min
50,000 req/month
ENTERPRISE
1,000 req/min
Unlimited / month

Individual API keys can have a custom limit via PATCH /apikeys/:id { rateLimit }. Effective limit = max(plan limit, key limit). On 429, the response includes retryAfter and the current plan/limit.

Health

GET/healthNo Auth

Service health check — database connectivity status.

Response
{ status: "ok", database: "connected" }

Authentication

POST/auth/registerNo Auth

Register a new user account.

Request Body
emailstring
passwordstring (min 8 chars)
namestring (optional)
Response
{ user, accessToken, refreshToken }
POST/auth/loginNo Auth

Login with email and password.

Request Body
emailstring
passwordstring
Response
{ user, accessToken, refreshToken }
POST/auth/refreshNo Auth

Refresh an expired access token.

Request Body
refreshTokenstring
Response
{ accessToken: string }
GET/auth/meJWT Required

Get the currently authenticated user profile.

Response
{ user: { id, email, name, plan, walletAddress } }

API Key Management

GET/apikeysJWT Required

List all your API keys (hashed for security).

Response
{ apiKeys: [...], limits: { maxApiKeys, remaining } }
POST/apikeysJWT Required

Create a new API key. The raw key is only shown once — store it immediately.

Request Body
namestring
permissionsstring[] (optional)
rateLimitnumber (optional)
Response
{ apiKey: "ilal_live_...", keyPrefix, id }
PATCH/apikeys/:idJWT Required

Update an API key name or rate limit.

Request Body
namestring (optional)
rateLimitnumber (optional)
Response
{ success: true, key: {...} }
DELETE/apikeys/:idJWT Required

Revoke and permanently delete an API key.

Response
{ success: true }

Onboarding — Institution Registration & Session

POST/onboarding/registerJWT or API Key

Register a wallet as a compliant institution (mock KYC — auto-approved). Safe to call multiple times; re-registers if wallet belongs to another account in demo mode.

Request Body
namestring — institution name
walletAddressaddress — wallet to onboard
countryCodenumber (optional) — ISO 3166-1 numeric, default 840 (US)
Response
{ success, institutionId, status: "approved", walletAddress, merkleIndex }
POST/onboarding/activate-session-demoJWT or API Key

TESTNET / DEV — Activate a 24h compliance session without a ZK proof. The ILAL relayer pays gas. Call after /onboarding/register. Idempotent — returns existing session info if already active.

Request Body
walletAddressaddress — wallet to activate
durationHoursnumber (optional) — session duration 1–720h, default 24
Response
{ success, txHash, expiresAt, gasUsed } or { alreadyActive: true, remainingSeconds }
POST/onboarding/activate-sessionJWT or API Key

PRODUCTION — Server-side ZK proof generation + on-chain session activation. Requires circuit files on the server.

Request Body
walletAddressaddress
expirynumber (optional) — unix timestamp
Response
{ success, txHash, sessionExpiry, expiresAt }
GET/onboarding/status/:addressJWT or API Key

Check institution onboarding status for a wallet.

Response
{ success, status: "approved"|"pending"|"not_registered", institutionId, merkleIndex }
GET/onboarding/attestation/:addressJWT or API Key

Get a fresh IssuerAttestation + Merkle proof for ZK proof generation.

Response
{ success, attestation: { userAddress, merkleRoot, merkleProof, merkleIndex, sigR8x, sigR8y, sigS, issuerAx, issuerAy } }

Testnet Utilities (Sandbox Only)

POST/testnet/activateJWT or API Key

TESTNET ONLY — Register + activate session in one call. No ZK proof needed. If wallet is already registered the registration step is skipped; if session is already active the activation step is skipped. Idempotent and safe to call repeatedly.

Request Body
walletAddressaddress — wallet to register and activate
durationHoursnumber (optional) — session duration 1–720h, default 24
namestring (optional) — institution name, auto-generated if omitted
Response
{ success, walletAddress, txHash, expiresAt, gasUsed } or { success, alreadyActive: true, remainingSeconds }
POST/testnet/activate-batchJWT or API Key

TESTNET ONLY — Activate up to 20 wallets in a single request. Processes sequentially to avoid nonce conflicts. Returns per-wallet results even if some fail.

Request Body
walletsstring[] — array of wallet addresses (max 20)
durationHoursnumber (optional) — session duration for all wallets, default 24
Response
{ total, succeeded, failed, results: [{ walletAddress, success, txHash | error }] }

DeFi — Preflight & Transaction Builder

GET/preflight/:addressJWT or API Key

Environment self-check. Returns session status, token balances, all allowances, and readiness in one call. Use before broadcasting to diagnose issues without on-chain trial-and-error.

Response
{ session: { active, remainingSeconds }, tokens: { WETH: { balance, decimals }, tUSDC: { balance, decimals } }, allowances: { WETH_to_SwapRouter, tUSDC_to_PositionManager, ... }, readiness: { canSwap, canAddLiquidity, issues: [] } }
POST/defi/swapJWT or API Key

Build an unsigned Uniswap V4 swap transaction. Returns calldata + preflight session + allowance check. Returns 412 SESSION_NOT_ACTIVE by default when session is inactive. Pass ?buildOnly=true to get unsigned TX data without session enforcement (useful for testing).

Request Body
tokenInaddress — token to sell (WETH: 0x4200...0006)
tokenOutaddress — token to buy (tUSDC: 0xa486...424D)
amountstring — positive integer in wei (exact input amount)
zeroForOneboolean (optional) — auto-derived from token ordering if omitted
userAddressaddress — wallet that will sign and broadcast
Query Params
buildOnlytrue | false (optional) — skip session check and return TX data even if session inactive. Default: false (returns 412 SESSION_NOT_ACTIVE when session is inactive).
Response
{ success, transaction: { to, data, value, chainId, gas }, preflight: { sessionActive, canBroadcastSafely, tokenSupported, allowanceSufficient, warning? }, authMethod }
POST/defi/liquidityJWT or API Key

Build an unsigned Uniswap V4 add-liquidity transaction. token0 must be < token1 (Uniswap sort order: WETH < tUSDC). Returns 412 SESSION_NOT_ACTIVE by default if session is inactive.

Request Body
token0address — must be < token1 (WETH: 0x4200...0006)
token1address — must be > token0 (tUSDC: 0xa486...424D)
amount0string — non-negative integer (at least one must be > 0)
amount1string — non-negative integer (at least one must be > 0)
tickLowernumber (optional) — default -600
tickUppernumber (optional) — default 600
userAddressaddress — wallet that will sign and broadcast
Query Params
buildOnlytrue | false (optional) — skip session check. Default: false.
Response
{ success, transaction: { to, data, value, chainId, gas }, preflight: { sessionActive, allowanceSufficient }, authMethod }

Usage & Billing

GET/usage/statsJWT or API Key

Get API usage statistics for the current billing period.

Response
{ usage: { totalCalls, successfulCalls, failedCalls, totalCost, byEndpoint }, quota: { limit, remaining, resetDate }, plan: { current, limits } } Note: limit = -1 means unlimited.
GET/billing/plansNo Auth

List available subscription plans and their limits.

Response
{ plans: [{ id, name, price, features }] }

HTTP Status Codes

200 OK
Request succeeded
201 Created
Resource created successfully
400 Bad Request
Invalid or missing parameters
401 Unauthorized
Missing or invalid API key / JWT — check the "code" field
403 Forbidden
Insufficient permissions or plan limit
404 Not Found
Resource does not exist
412 Precondition Failed
Compliance session not active (when requireActiveSession=true)
429 Too Many Requests
Rate limit exceeded
500 Internal Server Error
Unexpected server error