User Guide

Complete guide to setting up, configuring, and using your Secure Backend API.

Table of Contents

Installation & Setup

1. Clone or Download

Get the project files on your server or local machine.

git clone your-repository-url
cd project-directory

2. Install Dependencies

npm install

3. Configure Environment

cp .env.example .env
nano .env  # or your preferred editor

4. Start the Server

# Development
npm run dev

# Production
npm start
✓ Success! Server should be running on port 3000 (or your configured port)

Configuration Variables

Required Environment Variables

Variable Description Example
PORT Server port 3000
NODE_ENV Environment production
ALLOWED_ORIGINS CORS origins (comma-separated) https://yoursite.com
ALLOWED_DOMAINS Domain patterns (comma-separated) yoursite.com,*.yoursite.com

Optional: n8n Integration

Variable Description
N8N_WEBHOOK_URL Your n8n webhook endpoint
OAUTH_CLIENT_ID OAuth2 client ID (if using auth)
OAUTH_CLIENT_SECRET OAuth2 client secret
OAUTH_TOKEN_URL OAuth2 token endpoint

Optional: Security

Variable Description
ENABLE_IP_WHITELIST Enable IP filtering (true/false)
ALLOWED_IPS Comma-separated IP addresses

Project Architecture

Directory Structure

project/
├── config/              # Configuration management
│   └── index.js        # Centralized config from env vars
├── controllers/        # Request handlers
│   ├── contactController.js
│   └── businessContactController.js
├── middleware/         # Express middleware
│   ├── domainCors.js   # CORS by domain
│   ├── errorHandler.js # Global error handling
│   ├── ipWhitelist.js  # IP filtering
│   ├── requestLogger.js # Request/response logging
│   └── validateRequest.js # Input validation
├── routes/            # API route definitions
│   ├── index.js       # Main router
│   └── forms.js       # Form endpoints
├── services/          # Business logic
│   ├── formService.js
│   └── n8nService.js
├── utils/             # Helper functions
│   ├── logger.js
│   ├── oauth.js
│   └── RestClient.js
├── validation/        # Schema validation
│   ├── schemas.js
│   └── middleware.js
├── views/             # HTML pages
│   ├── components/
│   └── pages/
└── index.js           # Application entry point

Request Flow

  1. Request arrives → Express receives the HTTP request
  2. Logging → requestLogger captures request details
  3. Security → IP whitelist (optional), CORS validation
  4. Routing → Express matches route pattern
  5. Validation → Joi schema validates input
  6. Controller → Handles business logic
  7. Service → Processes data, calls external APIs
  8. Response → Returns JSON with debugId
  9. Error Handler → Catches any errors globally

Key Design Patterns

Adding New APIs

Step-by-Step Guide

1. Create Validation Schema

Add your schema to validation/schemas.js:

const myNewSchema = Joi.object({
  field1: Joi.string().required().min(2).max(100),
  field2: Joi.string().email().required(),
  field3: Joi.number().optional().min(0)
});

2. Create Service

Create services/myService.js for business logic:

const processMyData = async (data) => {
  // Your business logic here
  const processedData = {
    ...data,
    timestamp: new Date().toISOString()
  };

  return processedData;
};

module.exports = { processMyData };

3. Create Controller

Create controllers/myController.js:

const { processMyData } = require('../services/myService');
const { sendToN8n } = require('../services/n8nService');

const handleMyRequest = async (req, res, next) => {
  try {
    const processedData = await processMyData(req.body);

    // Optional: Send to n8n
    if (process.env.N8N_WEBHOOK_URL) {
      await sendToN8n('my_data_type', processedData, req);
    }

    res.json({
      success: true,
      data: processedData,
      debugId: req.debugId
    });
  } catch (error) {
    next(error);
  }
};

module.exports = { handleMyRequest };

4. Create Route

Add to routes/index.js or create new route file:

const express = require('express');
const router = express.Router();
const { validateRequest } = require('../validation/middleware');
const { myNewSchema } = require('../validation/schemas');
const { handleMyRequest } = require('../controllers/myController');

router.post('/my-endpoint',
  validateRequest(myNewSchema),
  handleMyRequest
);

module.exports = router;

5. Register Route

In routes/index.js, mount your router:

const myRoutes = require('./myRoutes');
router.use('/my', myRoutes);
✓ Done! Your API is now available at /api/my/my-endpoint

Use Case Examples

1. Contact Form Processor

Scenario: Receive contact form submissions from your website and forward to email/CRM.

Endpoints Used: POST /api/forms/contact

2. Business Lead Capture

Scenario: Capture qualified business leads with detailed information.

Endpoints Used: POST /api/forms/business-contact

3. Newsletter Signup

Scenario: Collect email addresses for marketing campaigns.

Implementation: Create custom endpoint following "Adding New APIs" guide

4. API Gateway

Scenario: Secure access to third-party APIs without exposing credentials.

Benefits: Hide API keys, add caching, implement rate limits

5. Webhook Receiver

Scenario: Receive webhooks from external services (Stripe, GitHub, etc.)

Implementation: Disable CORS for webhook endpoint, add signature validation

Framer Integration

Contact Form Example

Add this code to your Framer site to submit forms to the backend:

async function handleSubmit(event) {
  event.preventDefault();

  const formData = {
    name: event.target.name.value,
    email: event.target.email.value,
    subject: event.target.subject.value,
    message: event.target.message.value,
    consent: true
  };

  try {
    const response = await fetch('https://your-backend.com/api/forms/contact', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(formData)
    });

    const result = await response.json();

    if (result.success) {
      // Show success message
      console.log('Form submitted:', result.data.referenceId);
    } else {
      // Show error message
      console.error('Error:', result.error.message);
    }
  } catch (error) {
    console.error('Network error:', error);
  }
}

Business Contact Form

const businessData = {
  name: "John Smith",
  email: "john@company.com",
  phone: "+1-555-0123",
  businessName: "Acme Corp",
  businessType: "corporation",
  websiteUrl: "https://acme.com",
  message: "Interested in partnership",
  urgency: "medium",
  consent: true
};

const response = await fetch('https://your-backend.com/api/forms/business-contact', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(businessData)
});

n8n Workflow Setup

1. Create Webhook in n8n

2. Webhook Payload Format

The backend sends this structure to n8n:

{
  "type": "contact_form",
  "referenceId": "CONTACT-1698765432000",
  "debugId": "1698765432000-a1b2c3d4",
  "timestamp": "2025-10-26T10:30:32.000Z",
  "data": {
    "name": "John Doe",
    "email": "john@example.com",
    "subject": "Question",
    "message": "Hello..."
  },
  "metadata": {
    "ip": "192.168.1.1",
    "origin": "https://yoursite.com",
    "userAgent": "Mozilla/5.0..."
  }
}

3. Example n8n Workflow

Troubleshooting

Common Issues

CORS Error: "Not allowed by CORS"

Solution: Add your Framer site URL to ALLOWED_ORIGINS in .env

ALLOWED_ORIGINS=https://your-framer-site.framer.app
Validation Error: "Field is required"

Solution: Ensure all required fields are included in your request. Check the API documentation for each endpoint's required fields.

n8n Not Receiving Data

Solution:

Rate Limit Exceeded

Solution: Wait for the rate limit window to expire (typically 15 minutes to 1 hour) or contact the administrator to adjust rate limits.

Debug Mode

Enable debug logging for detailed information:

ENABLE_DEBUG_LOGGING=true

Finding Errors by Debug ID

Every response includes a debugId. Use it to search server logs:

grep "1698765432000-a1b2c3d4" logs/*.log

Need Help?

Check the full documentation or review server logs for detailed error information.

📚 View API Documentation 💚 Check Health