← Back to Documentation

BDM Universal API

Configuration Guide - Setup & Settings

Configuration Overview

The BDM Universal API uses a layered configuration approach with global settings, module-specific configurations, and environment variables.

Environment

.env file for sensitive data and deployment settings

Global Config

System-wide API settings in config/bdm_api.php

Module Config

Per-module settings in config/modules/

Environment Variables

Configure these settings in your .env file:

Application Settings

# Application
APP_NAME=BDM
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com

# Timezone
APP_TIMEZONE=Africa/Johannesburg

Note: Set APP_DEBUG=false in production to hide error details from API responses.

Database

# Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=bdm_production
DB_USERNAME=bdm_user
DB_PASSWORD=your_secure_password

Cache & Queue

# Cache (Redis recommended for production)
CACHE_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

# Queue (For webhooks, exports)
QUEUE_CONNECTION=redis

⚠️ Important: Redis is strongly recommended for production to handle rate limiting and caching efficiently.

Laravel Sanctum

# Sanctum
SANCTUM_STATEFUL_DOMAINS=yourdomain.com,api.yourdomain.com
SESSION_DOMAIN=.yourdomain.com
SESSION_SECURE_COOKIE=true

API Rate Limiting

# API Rate Limits
BDM_API_RATE_LIMIT_PER_MINUTE=100
BDM_API_RATE_LIMIT_PER_HOUR=5000
BDM_GUEST_RATE_LIMIT_PER_MINUTE=20
BDM_GUEST_RATE_LIMIT_PER_HOUR=100

Logging & Monitoring

# Logging
BDM_API_LOG_REQUESTS=true
BDM_API_LOG_REQUEST_BODY=true
BDM_API_LOG_RESPONSE_BODY=true
BDM_API_LOG_RETENTION_DAYS=90

# Performance
BDM_API_SLOW_QUERY_THRESHOLD=1000

Email (For Guest Access)

# Mail
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@yourdomain.com
MAIL_FROM_NAME="${APP_NAME}"

Global Configuration

Edit config/bdm_api.php for system-wide API settings:

<?php

return [
    /*
    |--------------------------------------------------------------------------
    | API Version
    |--------------------------------------------------------------------------
    */
    'version' => env('BDM_API_VERSION', 'v1'),

    /*
    |--------------------------------------------------------------------------
    | Pagination
    |--------------------------------------------------------------------------
    */
    'pagination' => [
        'default_per_page' => 15,
        'max_per_page' => 100,
    ],

    /*
    |--------------------------------------------------------------------------
    | Rate Limiting
    |--------------------------------------------------------------------------
    */
    'rate_limits' => [
        'authenticated' => [
            'per_minute' => env('BDM_API_RATE_LIMIT_PER_MINUTE', 100),
            'per_hour' => env('BDM_API_RATE_LIMIT_PER_HOUR', 5000),
        ],
        'api_token' => [
            'per_minute' => 200,
            'per_hour' => 10000,
        ],
        'guest' => [
            'per_minute' => env('BDM_GUEST_RATE_LIMIT_PER_MINUTE', 20),
            'per_hour' => env('BDM_GUEST_RATE_LIMIT_PER_HOUR', 100),
        ],
        'anonymous' => [
            'per_minute' => 10,
            'per_hour' => 50,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Request Logging
    |--------------------------------------------------------------------------
    */
    'logging' => [
        'enabled' => env('BDM_API_LOG_REQUESTS', true),
        'log_request_body' => env('BDM_API_LOG_REQUEST_BODY', true),
        'log_response_body' => env('BDM_API_LOG_RESPONSE_BODY', true),
        'max_body_length' => 10000,
        'retention_days' => env('BDM_API_LOG_RETENTION_DAYS', 90),
        'exclude_paths' => [
            '/api/health',
            '/api/status',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | CORS Configuration
    |--------------------------------------------------------------------------
    */
    'cors' => [
        'allowed_origins' => ['*'],
        'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
        'allowed_headers' => ['*'],
        'exposed_headers' => [
            'X-RateLimit-Limit',
            'X-RateLimit-Remaining',
            'X-RateLimit-Reset',
        ],
        'max_age' => 86400,
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication
    |--------------------------------------------------------------------------
    */
    'authentication' => [
        'token_prefix' => 'bdm_',
        'token_length' => 80,
        'guest_token_length' => 128,
    ],

    /*
    |--------------------------------------------------------------------------
    | Caching
    |--------------------------------------------------------------------------
    */
    'cache' => [
        'permission_ttl' => 900, // 15 minutes
        'user_module_list_ttl' => 3600, // 1 hour
    ],

    /*
    |--------------------------------------------------------------------------
    | Performance
    |--------------------------------------------------------------------------
    */
    'performance' => [
        'slow_query_threshold' => env('BDM_API_SLOW_QUERY_THRESHOLD', 1000),
        'enable_query_caching' => true,
    ],
];

Development Settings

  • • Higher rate limits
  • • Detailed logging enabled
  • • CORS set to allow all
  • • Request/response body logging

Production Settings

  • • Strict rate limits
  • • Selective logging
  • • Specific CORS origins
  • • Limited body logging

Module Configuration

Each module requires two configuration files in config/modules/:

1. Permissions Configuration

config/modules/bdm_accounting_permissions.php

<?php

return [
    /*
    |--------------------------------------------------------------------------
    | Available Roles
    |--------------------------------------------------------------------------
    */
    'roles' => [
        'owner' => [
            'label' => 'Owner',
            'permissions' => ['*'],
        ],
        'admin' => [
            'label' => 'Administrator',
            'permissions' => [
                'invoices.view',
                'invoices.create',
                'invoices.edit',
                'invoices.delete',
                'invoices.send',
                'expenses.view',
                'expenses.create',
                'expenses.edit',
                'expenses.delete',
                'reports.view',
                'reports.export',
            ],
        ],
        'manager' => [
            'label' => 'Manager',
            'permissions' => [
                'invoices.view',
                'invoices.create',
                'invoices.edit',
                'invoices.send',
                'expenses.view',
                'expenses.create',
                'expenses.edit',
                'reports.view',
            ],
        ],
        'staff' => [
            'label' => 'Staff Member',
            'permissions' => [
                'invoices.view',
                'invoices.create',
                'expenses.view',
                'expenses.create',
            ],
        ],
        'viewer' => [
            'label' => 'Read-Only Viewer',
            'permissions' => [
                'invoices.view',
                'expenses.view',
                'reports.view',
            ],
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Guest Access Defaults
    |--------------------------------------------------------------------------
    */
    'guest_access' => [
        'invoice' => [
            'default_permissions' => ['view', 'download', 'pay'],
            'default_expiry_days' => 30,
            'requires_password' => false,
            'requires_verification' => false,
        ],
        'expense' => [
            'default_permissions' => ['view'],
            'default_expiry_days' => 7,
            'requires_password' => true,
            'requires_verification' => false,
        ],
    ],
];

2. API Configuration

config/modules/bdm_accounting_api.php

<?php

return [
    /*
    |--------------------------------------------------------------------------
    | Searchable Fields
    |--------------------------------------------------------------------------
    */
    'searchable_fields' => [
        'invoices' => ['number', 'customer_name', 'customer_email'],
        'expenses' => ['description', 'vendor', 'category'],
    ],

    /*
    |--------------------------------------------------------------------------
    | Sortable Fields
    |--------------------------------------------------------------------------
    */
    'sortable_fields' => [
        'invoices' => ['number', 'total', 'due_date', 'created_at'],
        'expenses' => ['amount', 'date', 'created_at'],
    ],

    /*
    |--------------------------------------------------------------------------
    | Filterable Fields
    |--------------------------------------------------------------------------
    */
    'filterable_fields' => [
        'invoices' => ['status', 'customer_id'],
        'expenses' => ['category', 'payment_method'],
    ],

    /*
    |--------------------------------------------------------------------------
    | Pagination
    |--------------------------------------------------------------------------
    */
    'default_per_page' => 15,
    'max_per_page' => 100,

    /*
    |--------------------------------------------------------------------------
    | Webhook Events
    |--------------------------------------------------------------------------
    */
    'webhook_events' => [
        'invoice.created' => 'Invoice Created',
        'invoice.updated' => 'Invoice Updated',
        'invoice.sent' => 'Invoice Sent',
        'invoice.paid' => 'Invoice Paid',
        'invoice.overdue' => 'Invoice Overdue',
        'expense.created' => 'Expense Created',
        'expense.approved' => 'Expense Approved',
    ],
];

Authentication Configuration

Sanctum Configuration

Edit config/sanctum.php:

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost')),

'expiration' => null, // Never expire (or set in minutes)

'middleware' => [
    'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
    'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],

API Token Settings

# config/bdm_api.php

'authentication' => [
    // Token prefix for API tokens
    'token_prefix' => 'bdm_',
    
    // Length of API tokens
    'token_length' => 80,
    
    // Length of guest access tokens
    'guest_token_length' => 128,
    
    // Token expiration (null = never)
    'token_expiration' => null,
];

🔒 Security Best Practices

  • ✓ Use HTTPS in production (SESSION_SECURE_COOKIE=true)
  • ✓ Set specific SANCTUM_STATEFUL_DOMAINS
  • ✓ Never commit .env file to version control
  • ✓ Rotate API tokens regularly
  • ✓ Use environment-specific configurations

Rate Limiting Configuration

Default Rate Limits

Type Per Minute Per Hour Config
Authenticated User 100 5,000 BDM_API_RATE_LIMIT_*
API Token 200 10,000 Per token config
Guest Access 20 100 BDM_GUEST_RATE_LIMIT_*
Anonymous 10 50 Fixed in config

Custom Rate Limits

# .env - Adjust these values

# Development (higher limits)
BDM_API_RATE_LIMIT_PER_MINUTE=200
BDM_API_RATE_LIMIT_PER_HOUR=10000

# Production (standard)
BDM_API_RATE_LIMIT_PER_MINUTE=100
BDM_API_RATE_LIMIT_PER_HOUR=5000

# Guest Access (stricter)
BDM_GUEST_RATE_LIMIT_PER_MINUTE=20
BDM_GUEST_RATE_LIMIT_PER_HOUR=100

Per-Token Rate Limits

Set custom limits when creating API tokens:

POST /api/tokens

{
  "name": "High Volume Integration",
  "scopes": ["accounting.*"],
  "rate_limit_per_minute": 500,  // Custom limit
  "rate_limit_per_hour": 20000   // Custom limit
}

CORS Configuration

Development Setup

Edit config/cors.php:

'paths' => ['api/*'],

'allowed_methods' => ['*'],

'allowed_origins' => ['*'], // Allow all in development

'allowed_origins_patterns' => [],

'allowed_headers' => ['*'],

'exposed_headers' => [
    'X-RateLimit-Limit',
    'X-RateLimit-Remaining',
    'X-RateLimit-Reset',
],

'max_age' => 0,

'supports_credentials' => true,

Production Setup

'allowed_origins' => [
    'https://yourdomain.com',
    'https://app.yourdomain.com',
    'https://admin.yourdomain.com',
],

'allowed_origins_patterns' => [
    '/^https:\/\/.*\.yourdomain\.com$/', // Allow all subdomains
],

'max_age' => 86400, // Cache preflight for 24 hours

⚠️ Security Warning

Never use 'allowed_origins' => ['*'] in production. Always specify exact domains or use patterns.

Security Configuration

Guest Access Security

# config/bdm_guest_access.php

return [
    'token_length' => 128,
    
    'password' => [
        'min_length' => 6,
        'require_special_chars' => false,
    ],
    
    'verification_code' => [
        'length' => 6,
        'expiry_minutes' => 15,
    ],
    
    'device_tracking' => [
        'enabled' => true,
        'max_devices' => 3,
    ],
    
    'ip_restrictions' => [
        'enabled' => true,
        'max_ips' => 5,
    ],
];

Password Hashing

# config/hashing.php

'bcrypt' => [
    'rounds' => env('BCRYPT_ROUNDS', 12), // Higher = more secure but slower
],

Session Security

# .env

SESSION_DRIVER=redis
SESSION_LIFETIME=120
SESSION_SECURE_COOKIE=true  # HTTPS only
SESSION_HTTP_ONLY=true      # Prevent JavaScript access
SESSION_SAME_SITE=lax       # CSRF protection

🔐 Security Checklist

  • ☑ Use HTTPS in production
  • ☑ Enable secure cookies (SESSION_SECURE_COOKIE=true)
  • ☑ Set strong BCRYPT_ROUNDS (10-12)
  • ☑ Configure CORS properly
  • ☑ Use Redis for sessions and cache
  • ☑ Enable rate limiting
  • ☑ Set appropriate token expiration
  • ☑ Regularly review access logs

Logging Configuration

Request Logging

# config/bdm_api.php

'logging' => [
    'enabled' => true,
    
    // Log request body (careful with sensitive data)
    'log_request_body' => env('BDM_API_LOG_REQUEST_BODY', true),
    
    // Log response body
    'log_response_body' => env('BDM_API_LOG_RESPONSE_BODY', true),
    
    // Max length of request/response body to log
    'max_body_length' => 10000,
    
    // Retention period for logs
    'retention_days' => env('BDM_API_LOG_RETENTION_DAYS', 90),
    
    // Exclude specific paths from logging
    'exclude_paths' => [
        '/api/health',
        '/api/status',
        '/api/metrics',
    ],
    
    // Exclude sensitive fields from logging
    'exclude_fields' => [
        'password',
        'password_confirmation',
        'credit_card',
        'cvv',
    ],
];

Log Cleanup

Schedule log cleanup in app/Console/Kernel.php:

protected function schedule(Schedule $schedule)
{
    // Clean up old API request logs daily
    $schedule->command('bdm:cleanup-logs')
        ->daily()
        ->at('02:00');
}

💾 Storage Considerations

Request logging can consume significant disk space. For high-traffic APIs:

  • • Reduce retention period (30-60 days)
  • • Disable body logging in production
  • • Use log aggregation services (ELK, Papertrail)
  • • Archive logs to S3/cloud storage

Performance Optimization

Caching Strategy

# config/bdm_api.php

'cache' => [
    // Cache permission checks for 15 minutes
    'permission_ttl' => 900,
    
    // Cache user's module list for 1 hour
    'user_module_list_ttl' => 3600,
    
    // Cache API responses (per endpoint config)
    'response_cache_enabled' => false,
];

Database Optimization

# config/database.php

'mysql' => [
    // ... other settings
    
    'strict' => true,
    'engine' => 'InnoDB',
    
    // Connection pooling
    'pool' => [
        'size' => 10,
    ],
    
    // Query caching
    'options' => [
        PDO::ATTR_PERSISTENT => true,
    ],
];

Queue Configuration

# config/queue.php

'connections' => [
    'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
        'queue' => env('REDIS_QUEUE', 'default'),
        'retry_after' => 90,
        'block_for' => null,
        'after_commit' => false,
    ],
],

✓ Performance Best Practices

  • • Use Redis for cache & sessions
  • • Enable query caching
  • • Optimize database indexes
  • • Use eager loading
  • • Queue heavy operations
  • • Enable response compression

📊 Monitoring

  • • Track slow queries (>1s)
  • • Monitor rate limit hits
  • • Watch memory usage
  • • Check queue depths
  • • Monitor error rates
  • • Track API response times

Webhook Configuration

Webhook Settings

# config/bdm_webhooks.php

return [
    'retry' => [
        'max_attempts' => 3,
        'backoff' => [
            1 => 60,    // 1 minute after first failure
            2 => 300,   // 5 minutes after second
            3 => 1800,  // 30 minutes after third
        ],
    ],
    
    'timeout' => 30, // Seconds
    
    'signature' => [
        'enabled' => true,
        'algorithm' => 'sha256',
        'header' => 'X-BDM-Signature',
    ],
    
    'rate_limit' => [
        'per_minute' => 100,
    ],
];

Queue Configuration for Webhooks

# .env

QUEUE_CONNECTION=redis

# Webhook-specific queue
WEBHOOK_QUEUE=webhooks

🔔 Webhook Reliability

Ensure webhook delivery with:

  • • Queue workers running (php artisan queue:work)
  • • Supervisor for worker management
  • • Retry logic with exponential backoff
  • • Delivery logging and monitoring
  • • Signature verification on receiving end

Environment-Specific Configurations

🛠️ Development

  • APP_DEBUG: true
  • CORS: Allow all
  • Rate Limits: High
  • Logging: Verbose
  • Cache: File/Database
  • Cookies: Not secure

🧪 Staging

  • APP_DEBUG: false
  • CORS: Staging domains
  • Rate Limits: Production-like
  • Logging: Standard
  • Cache: Redis
  • Cookies: Secure

🚀 Production

  • APP_DEBUG: false
  • CORS: Strict domains
  • Rate Limits: Enforced
  • Logging: Essential only
  • Cache: Redis (required)
  • Cookies: Secure + SameSite