Skip to content

API Structure

Rate Limiting

Strategy: Token Bucket

Rate limiting uses @nestjs/throttler with tiered limits. Production deployments should use Redis adapter for distributed rate limiting across multiple instances.

typescript
// nestjs-throttler with PostgreSQL storage
@Module({
  imports: [
    ThrottlerModule.forRoot({
      throttlers: [
        { name: 'short', ttl: 1000, limit: 10 },   // 10 req/sec
        { name: 'medium', ttl: 60000, limit: 100 }, // 100 req/min
        { name: 'long', ttl: 3600000, limit: 1000 } // 1000 req/hour
      ],
      storage: new ThrottlerStorageService() // DB-backed
    })
  ]
})

Per-Endpoint Limits

Endpoint CategoryLimit
Auth (login, register)5/min
Password reset3/hour
Payment webhooks100/sec
API general100/min
Admin endpoints200/min

Financial Endpoint Rate Limits

EndpointLimit
POST /mlm/payouts/request1/min per user
POST /investment/participations3/min per user
POST /cart/checkout2/min per user
PATCH /users/me (payout details)3/hour per user
POST /admin/commissions/approve10/min per admin
POST /admin/payouts/process5/min per admin

Implementation

typescript
// Custom decorator for financial endpoints
export const FinancialRateLimit = () =>
  applyDecorators(
    Throttle({ default: { limit: 1, ttl: 60000 } }), // 1 per minute
    UseGuards(ThrottlerGuard),
  );

// Usage in controller
@Controller('mlm/payouts')
export class PayoutsController {
  @Post('request')
  @FinancialRateLimit()
  async requestPayout(@CurrentUser() user: User, @Body() dto: PayoutRequestDto) {
    return this.payoutService.createRequest(user.partnerId, dto);
  }
}

User-Specific Rate Limiting

For financial endpoints, rate limiting must be per-user, not per-IP:

typescript
@Injectable()
export class UserThrottlerGuard extends ThrottlerGuard {
  protected async getTracker(req: Request): Promise<string> {
    // Use user ID for authenticated requests (prevents shared IP issues)
    const user = req.user as AuthenticatedUser;
    if (user?.id) {
      return `user:${user.id}`;
    }
    // Fall back to IP for unauthenticated requests
    return req.ip;
  }
}

Rate Limit Headers

Financial endpoints include additional headers for transparency:

X-RateLimit-Limit: 1
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705329600
X-RateLimit-Policy: financial

Rate Limit Response

json
{
  "statusCode": 429,
  "message": "Too Many Requests",
  "retryAfter": 45
}

Endpoints Overview

/api/v1
├── /auth
│   ├── POST /register
│   ├── POST /login
│   ├── POST /refresh
│   ├── POST /logout
│   └── POST /2fa/*

├── /users
│   ├── GET /me
│   ├── PATCH /me
│   └── /kyc/*

├── /investment
│   ├── GET /strategies
│   ├── GET /strategies/:id
│   ├── POST /participations
│   ├── GET /participations
│   └── GET /portfolio

├── /products
│   ├── GET /
│   ├── GET /:id
│   ├── GET /categories
│   └── POST /reviews

├── /cart
│   ├── GET /
│   ├── POST /items
│   ├── PATCH /items/:id
│   ├── DELETE /items/:id
│   └── POST /checkout

├── /orders
│   ├── GET /
│   ├── GET /:id
│   └── GET /:id/tracking

├── /mlm
│   ├── /partner
│   │   ├── GET /me
│   │   ├── GET /network
│   │   └── GET /network/stats
│   │
│   ├── /referrals
│   │   ├── GET /links
│   │   ├── POST /links
│   │   └── GET /links/:id/stats
│   │
│   ├── /commissions
│   │   ├── GET /
│   │   ├── GET /summary
│   │   └── GET /history
│   │
│   ├── /ranks
│   │   ├── GET /current
│   │   ├── GET /progress
│   │   └── GET /history
│   │
│   └── /payouts
│       ├── GET /balance
│       ├── POST /request
│       └── GET /history

└── /admin  (Super Admin)
    ├── /users/*
    ├── /partners/*
    ├── /commissions/*
    ├── /products/*
    ├── /strategies/*
    └── /analytics/*