Developer CenterGuidesAutomating Monthly Reporting

    Automating Monthly Reporting

    Automate your monthly Metro 2 submissions to ensure consistency, reduce manual effort, and never miss a bureau reporting deadline.

    1. Why Automate Monthly Reporting

    Manual monthly submissions are error-prone and difficult to scale. Automation addresses the three biggest challenges in credit reporting:

    Consistency

    Automated submissions run the same way every time, eliminating human error in data preparation and formatting.

    Reduced Manual Work

    Free your team from monthly export-format-upload cycles. Once configured, submissions happen without intervention.

    Bureau Deadlines

    Bureaus expect data within a specific window each month. Automated scheduling ensures you never miss a deadline.

    2. Dashboard Scheduling (No-Code)

    The simplest way to automate is through the Metro 2 dashboard. Navigate to Settings > Scheduling to configure your monthly submission schedule without writing any code.

    Step 1: Set Your Reporting Day

    Choose the day of the month when submissions should run (e.g., the 1st or 15th). The system will automatically submit all active records on that day.

    Step 2: Select Target Bureaus

    Choose which credit bureaus to submit to: Equifax, Experian, TransUnion, or all three. Each bureau can have a different schedule if needed.

    Step 3: Configure Notifications

    Set up email or webhook notifications to be alerted when submissions complete or fail. You can add multiple recipients.

    3. API-Based Scheduling

    For programmatic control, use the Schedules API to create and manage reporting schedules:

    // Create a monthly schedule
    POST /api/v1/schedules
    Content-Type: application/json
    Authorization: Bearer your_api_key
    
    {
      "name": "Monthly Bureau Submission",
      "frequency": "monthly",
      "dayOfMonth": 1,
      "time": "06:00",
      "timezone": "America/New_York",
      "bureaus": ["equifax", "experian", "transunion"],
      "includeAllActive": true,
      "notifications": {
        "webhookUrl": "https://your-app.com/webhooks/schedule",
        "emailRecipients": ["compliance@yourcompany.com"]
      }
    }
    // Response
    {
      "scheduleId": "sched_abc123",
      "status": "active",
      "nextRun": "2025-04-01T06:00:00-04:00",
      "createdAt": "2025-03-15T10:30:00Z"
    }
    
    // List all schedules
    GET /api/v1/schedules
    
    // Update a schedule
    PATCH /api/v1/schedules/sched_abc123
    {
      "dayOfMonth": 5,
      "time": "08:00"
    }
    
    // Pause a schedule
    POST /api/v1/schedules/sched_abc123/pause
    
    // Resume a schedule
    POST /api/v1/schedules/sched_abc123/resume
    
    // Delete a schedule
    DELETE /api/v1/schedules/sched_abc123

    4. Cron Job Integration

    If you prefer to manage scheduling in your own infrastructure, use a cron job that calls the Metro 2 API directly:

    # Common cron patterns for credit reporting
    
    # Run on the 1st of every month at 6:00 AM EST
    0 6 1 * *   /usr/local/bin/node /opt/scripts/submit-metro2.js
    
    # Run on the 15th of every month at midnight
    0 0 15 * *  /usr/local/bin/node /opt/scripts/submit-metro2.js
    
    # Run every Monday (for weekly test submissions in sandbox)
    0 9 * * 1   /usr/local/bin/node /opt/scripts/submit-metro2.js --sandbox
    // /opt/scripts/submit-metro2.js
    const fetch = require('node-fetch');
    
    async function runMonthlySubmission() {
      const API_KEY = process.env.METRO2_API_KEY;
      const BASE_URL = 'https://api.metro2.switchlabs.dev/v1';
    
      try {
        // Step 1: Trigger a submission for all active records
        const response = await fetch(`${BASE_URL}/submissions`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${API_KEY}`
          },
          body: JSON.stringify({
            type: 'monthly',
            includeAllActive: true,
            bureaus: ['equifax', 'experian', 'transunion']
          })
        });
    
        if (!response.ok) {
          throw new Error(`Submission failed: ${response.status}`);
        }
    
        const result = await response.json();
        console.log(`Submission ${result.submissionId} started`);
        console.log(`Records: ${result.recordCount}`);
    
        // Step 2: Optionally notify your team
        await notifySlack(`Metro 2 monthly submission started: ${result.recordCount} records`);
    
      } catch (error) {
        console.error('Monthly submission failed:', error.message);
        await notifySlack(`Metro 2 submission FAILED: ${error.message}`);
        process.exit(1);
      }
    }
    
    runMonthlySubmission();

    5. Monitoring Automated Submissions via Webhooks

    Configure webhooks to receive real-time notifications about your automated submissions. The key events to listen for:

    // Event: schedule.triggered
    {
      "event": "schedule.triggered",
      "scheduleId": "sched_abc123",
      "submissionId": "sub_xyz789",
      "timestamp": "2025-04-01T06:00:00Z",
      "recordCount": 12450
    }
    
    // Event: submission.completed
    {
      "event": "submission.completed",
      "submissionId": "sub_xyz789",
      "timestamp": "2025-04-01T06:02:30Z",
      "summary": {
        "total": 12450,
        "accepted": 12438,
        "rejected": 12,
        "bureaus": {
          "equifax": { "status": "accepted", "confirmationId": "EQ-20250401-001" },
          "experian": { "status": "accepted", "confirmationId": "EX-20250401-001" },
          "transunion": { "status": "accepted", "confirmationId": "TU-20250401-001" }
        }
      }
    }
    
    // Event: submission.failed
    {
      "event": "submission.failed",
      "submissionId": "sub_xyz789",
      "timestamp": "2025-04-01T06:01:15Z",
      "error": {
        "code": "VALIDATION_ERROR",
        "message": "Header record missing required fields"
      }
    }

    6. Troubleshooting Failed Automated Runs

    When an automated submission fails, follow these steps to diagnose and resolve the issue:

    VALIDATION_ERROR

    One or more records failed validation. Check the errors endpoint for the specific submission to see which records and fields caused the failure. Fix the data and resubmit manually.

    AUTH_EXPIRED

    Your API key may have expired or been rotated. Generate a new key in the dashboard and update your schedule or cron job configuration.

    BUREAU_REJECTED

    The bureau rejected the entire file. This typically means the header or trailer record has formatting issues. Check the bureau-specific error code in the rejection details.

    NO_ACTIVE_RECORDS

    The scheduled run found no active records to submit. This may indicate a data source issue or all records have been closed. Check your record statuses in the dashboard.

    Tip

    Set up webhook notifications for schedule.triggered and submission.completed events. This way your team is automatically notified of every monthly run without needing to check the dashboard.

    Related Resources

    API Reference

    • • POST /api/v1/schedules — Create a schedule
    • • GET /api/v1/schedules — List schedules
    • • POST /api/v1/submissions — Manual submission trigger