DDC Backend API

Debt Collection Agency API Documentation

DDC Backend API

A RESTful API backend for a debt collection agency built with AdonisJS 6 and PostgreSQL. This system is designed for global, email-centric debt collection with OTP-based authentication support.

Features

Tech Stack

Prerequisites

Installation

  1. Clone the repository and navigate to the project directory:
cd ddc-backend
  1. Install dependencies:
npm install
  1. Copy the environment example file and configure it:
cp .env.example .env
  1. Copy .env.example to .env and update if needed:
cp .env.example .env

The .env.example file already contains the Neon PostgreSQL connection details. If you need to change them, edit the .env file:

PORT=3333
HOST=0.0.0.0
NODE_ENV=development
APP_KEY=your-app-key-here
APP_NAME=Debt Collection Agency API
APP_URL=https://ddc-api.streamlinelab.co  # Production URL (optional, defaults to http://HOST:PORT)

# Database Configuration (Neon PostgreSQL)
DB_CONNECTION=pg
DB_HOST=ep-long-hall-ag615knm-pooler.c-2.eu-central-1.aws.neon.tech
DB_PORT=5432
DB_USER=neondb_owner
DB_PASSWORD=npg_zbYUF45ZoKSr
DB_DATABASE=neondb
DB_SSL=true  # Required for Neon PostgreSQL
  1. Generate an application key:
node ace generate:key

Copy the generated key to APP_KEY in your .env file.

  1. Run database migrations:
npm run migration:run

Running the Application

Development Mode

npm run dev

The API will be available at http://localhost:3333

Production Mode

npm run build
npm start

Production URL: https://ddc-api.streamlinelab.co/

Make sure to set the APP_URL environment variable in production:

APP_URL=https://ddc-api.streamlinelab.co

This is important for email tracking URLs and other absolute URL generation.

API Endpoints

Health Check

Debtors

Query Parameters for GET /debtors:

Response includes:

Debts

Query Parameters for GET /debts:

Payments

Query Parameters for GET /payments:

Dashboard

Response includes:

Communication Templates

Query Parameters for GET /communication-templates:

Request Body for POST /communication-templates/process:

Debtor Authentication (Public)

Request Body for POST /debtors/auth/request-otp:

{
  "mobilePhone": "+1234567890"
}

Request Body for POST /debtors/auth/verify-otp:

{
  "mobilePhone": "+1234567890",
  "otpCode": "1234"
}

Response from verify-otp includes:

Debtor Portal (Protected - Requires JWT Authentication)

All endpoints require Authorization: Bearer <jwt_token> header.

Response from GET /debtors/me/debts includes:

Debtor Deferral Requests (Protected - Requires JWT Authentication)

All endpoints require Authorization: Bearer <jwt_token> header.

Request Body for POST /debtors/me/deferral-requests:

{
  "debtId": "550e8400-e29b-41d4-a716-446655440001",
  "requestedDeferralDays": 30,
  "reason": "I am experiencing temporary financial hardship and need additional time to arrange payment."
}

Response includes:

Validation Rules:

Deferral Requests Management (Backoffice)

Endpoints for managing deferral requests (requires backoffice authentication).

Query Parameters for GET /deferral-requests:

Request Body for PUT /deferral-requests/:id/approve:

{
  "status": "approved",
  "reviewNotes": "Approved based on debtor's payment history and current circumstances."
}

Request Body for PUT /deferral-requests/:id/reject:

{
  "status": "rejected",
  "reviewNotes": "Rejected due to insufficient documentation."
}

Response includes:

Database Schema

The database uses UUID primary keys and supports:

Key Tables:

Example API Requests

Request OTP for Debtor Login

# Development
curl -X POST http://localhost:3333/debtors/auth/request-otp \
  -H "Content-Type: application/json" \
  -d '{
    "mobilePhone": "+1234567890"
  }'

# Production
curl -X POST https://ddc-api.streamlinelab.co/debtors/auth/request-otp \
  -H "Content-Type: application/json" \
  -d '{
    "mobilePhone": "+1234567890"
  }'

Verify OTP and Get JWT Token

# Development
curl -X POST http://localhost:3333/debtors/auth/verify-otp \
  -H "Content-Type: application/json" \
  -d '{
    "mobilePhone": "+1234567890",
    "otpCode": "1234"
  }'

# Production
curl -X POST https://ddc-api.streamlinelab.co/debtors/auth/verify-otp \
  -H "Content-Type: application/json" \
  -d '{
    "mobilePhone": "+1234567890",
    "otpCode": "1234"
  }'

Get Debtor's Debts (Protected)

# Development
curl -X GET http://localhost:3333/debtors/me/debts \
  -H "Authorization: Bearer <jwt_token>"

# Production
curl -X GET https://ddc-api.streamlinelab.co/debtors/me/debts \
  -H "Authorization: Bearer <jwt_token>"

Submit Deferral Request (Protected)

# Development
curl -X POST http://localhost:3333/debtors/me/deferral-requests \
  -H "Authorization: Bearer <jwt_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "debtId": "550e8400-e29b-41d4-a716-446655440001",
    "requestedDeferralDays": 30,
    "reason": "I am experiencing temporary financial hardship and need additional time to arrange payment."
  }'

# Production
curl -X POST https://ddc-api.streamlinelab.co/debtors/me/deferral-requests \
  -H "Authorization: Bearer <jwt_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "debtId": "550e8400-e29b-41d4-a716-446655440001",
    "requestedDeferralDays": 30,
    "reason": "I am experiencing temporary financial hardship and need additional time to arrange payment."
  }'

Get My Deferral Requests (Protected)

# Development
curl -X GET http://localhost:3333/debtors/me/deferral-requests \
  -H "Authorization: Bearer <jwt_token>"

# Production
curl -X GET https://ddc-api.streamlinelab.co/debtors/me/deferral-requests \
  -H "Authorization: Bearer <jwt_token>"

List All Deferral Requests (Backoffice)

# Development
curl -X GET "http://localhost:3333/deferral-requests?status=pending" \
  -H "Authorization: Bearer <backoffice_token>"

# Production
curl -X GET "https://ddc-api.streamlinelab.co/deferral-requests?status=pending" \
  -H "Authorization: Bearer <backoffice_token>"

Approve Deferral Request (Backoffice)

# Development
curl -X PUT http://localhost:3333/deferral-requests/550e8400-e29b-41d4-a716-446655440002/approve \
  -H "Authorization: Bearer <backoffice_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "approved",
    "reviewNotes": "Approved based on debtor payment history."
  }'

# Production
curl -X PUT https://ddc-api.streamlinelab.co/deferral-requests/550e8400-e29b-41d4-a716-446655440002/approve \
  -H "Authorization: Bearer <backoffice_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "approved",
    "reviewNotes": "Approved based on debtor payment history."
  }'

Reject Deferral Request (Backoffice)

# Development
curl -X PUT http://localhost:3333/deferral-requests/550e8400-e29b-41d4-a716-446655440002/reject \
  -H "Authorization: Bearer <backoffice_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "rejected",
    "reviewNotes": "Insufficient documentation provided."
  }'

# Production
curl -X PUT https://ddc-api.streamlinelab.co/deferral-requests/550e8400-e29b-41d4-a716-446655440002/reject \
  -H "Authorization: Bearer <backoffice_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "rejected",
    "reviewNotes": "Insufficient documentation provided."
  }'

Create a Debtor

# Development
curl -X POST http://localhost:3333/debtors \

# Production
curl -X POST https://ddc-api.streamlinelab.co/debtors \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "mobilePhone": "+1234567890",
    "legalEntity": "ABC Corp",
    "dob": "1980-01-15",
    "addressLine1": "123 Main St",
    "addressLine2": "Apt 4B",
    "city": "London",
    "regionState": "Greater London",
    "postalCode": "SW1A 1AA",
    "countryCode": "GB",
    "languagePreference": "English"
  }'

Create a Debt

# Development
curl -X POST http://localhost:3333/debts \

# Production
curl -X POST https://ddc-api.streamlinelab.co/debts \
  -H "Content-Type: application/json" \
  -d '{
    "debtorId": "550e8400-e29b-41d4-a716-446655440000",
    "originalCreditor": "ABC Credit Corp",
    "currencyCode": "GBP",
    "originalBalance": 5000.00,
    "currentBalance": 5000.00,
    "currentStatus": "active",
    "placementDate": "2024-01-01",
    "p2pScore": 0.750
  }'

Record a Payment

# Development
curl -X POST http://localhost:3333/payments \

# Production
curl -X POST https://ddc-api.streamlinelab.co/payments \
  -H "Content-Type: application/json" \
  -d '{
    "debtId": "550e8400-e29b-41d4-a716-446655440001",
    "amount": 500.00,
    "currencyCode": "GBP",
    "paymentMethod": "bank_transfer",
    "status": "completed",
    "processorTxnId": "TXN-12345"
  }'

Get Dashboard Statistics

# Development
curl -X GET http://localhost:3333/dashboard/stats

# Production
curl -X GET https://ddc-api.streamlinelab.co/dashboard/stats

Process Communication Template

# Development
curl -X POST http://localhost:3333/communication-templates/process \

# Production
curl -X POST https://ddc-api.streamlinelab.co/communication-templates/process \
  -H "Content-Type: application/json" \
  -d '{
    "template_name": "final_email_warning",
    "debtor_id": "550e8400-e29b-41d4-a716-446655440000",
    "debt_id": "550e8400-e29b-41d4-a716-446655440001",
    "send": true
  }'

Database Migrations

Run Migrations

npm run migration:run

Rollback Last Migration

npm run migration:rollback

Fresh Migration (Drops all tables and recreates)

npm run migration:fresh

Check Migration Status

npm run migration:status

Project Structure

ddc-backend/
├── app/
│   ├── controllers/       # API controllers
│   ├── models/            # Database models
│   ├── validators/        # Request validators
│   ├── services/          # Business logic services (OTP, JWT, SMS, Email, Voice, Strategy, Segment Assignment)
│   ├── jobs/              # Background jobs (template processing)
│   ├── commands/          # Ace commands (strategy engine, template processing)
│   ├── middleware/        # HTTP middleware (authentication, JSON response)
│   └── exceptions/        # Exception handlers
├── config/                # Configuration files
├── database/
│   └── migrations/        # Database migrations
├── start/
│   ├── routes.ts         # Route definitions
│   ├── kernel.ts         # Middleware configuration
│   └── env.ts            # Environment validation
├── server.ts             # Application entry point
└── package.json

Commands

Strategy Engine

Run the daily collection strategy engine:

node ace strategy:run

What it does:

  1. Re-assigns segments for all active debts based on current attributes (P2P score, balance, days since placement)
  2. Processes TimeTrigger rules for each segment, sending communications based on placement dates
  3. Logs all segment assignments to the segment_assignment table for audit purposes

The strategy engine ensures debts are in the correct segments before processing communication rules.

P2P Scoring Configuration

The P2P scoring system uses a configuration table (p2p_scoring_config) to store all weights and parameters. The configuration is stored as JSONB with the following structure:

{
  "combine": {
    "engagement": 0.40,
    "contactability": 0.25,
    "payment": 0.25,
    "debt_pressure": 0.10
  },
  "digital_weights": {
    "login": 0.10,
    "view_balance": 0.25,
    "document_download": 0.40,
    "chat_initiated": 0.70,
    "payment_attempt": 1.00
  },
  "half_life_days": {
    "engagement": 7,
    "contactability": 14,
    "payment": 30,
    "age": 180
  },
  "normalization": {
    "engagement_norm_cap": 2.0
  },
  "contactability_outcome_points": {
    "rpc": 1.0,
    "replied": 0.85,
    "opened": 0.60,
    "delivered": 0.40,
    "no_answer": 0.15,
    "bounced": 0.0,
    "failed": 0.0
  },
  "balance_scale": {
    "denominator": 5000
  }
}

Configuration Fields:

Only one configuration can be active at a time (enforced by unique index on is_active = true).

Process Communication Templates

Process and optionally send communication templates:

# Process all active templates
node ace process:communication-templates

# Process specific template
node ace process:communication-templates final_email_warning

# Process by type
node ace process:communication-templates --type=email

# Process and send (requires debtor and debt IDs)
node ace process:communication-templates --debtorId=<uuid> --debtId=<uuid> --send

Notes

License

This project is private and proprietary.