Skip to content
Last updated

Getting Started: Borrower Campaigns with Bulk Sender

This tutorial will guide you through creating your first borrower campaign with bulk sender functionality. Bulk senders allow you to automatically send communications (emails, text messages, etc.) to borrowers based on query results from Redash.

Overview

Borrower campaigns with bulk senders enable you to:

  • Query your borrower data using Redash
  • Automatically send communications to borrowers matching your query criteria
  • Schedule campaigns to run automatically on a recurring basis
  • Track campaign execution and results

The workflow consists of three main components:

  1. Redash Query: Defines which borrowers to target
  2. Bulk Sender: Configures what message to send and how
  3. Campaign: Ties everything together and optionally schedules execution

Prerequisites

Before you begin, ensure you have:

  • Access to Redash with a query that returns borrower data
  • A Redash API key (found at https://{YOUR_REDASH_DOMAIN}/users/me)

Step 1: Create a Redash Query

Your Redash query must return at least a borrowerId column. You can use either:

  • Public IDs (e.g., BO-XXXX-XXXX)
  • Internal database IDs (integers)

Example Query

Specify a SQL query targeting the borrowers you care about:

select distinct 
  lp.person_id as "borrowerId",
  l.id as "loanId"
from
  loans l
join loan_people lp on lp.loan_id = l.id
join people p on lp.person_id = p.id
where
  l.status = 'Active' 
  and {other properties of loans or borrowers you care about};

Important: The column must be named exactly borrowerId (case-sensitive).

Query Result Format

For basic bulk sending, your query result could look like:

borrowerId,loanId
100,200
103,205
...

Custom Context Variables

You can pass custom data to your message templates by prefixing columns with context.. For example:

SELECT 
    b.id AS "borrowerId",
    l.id AS "loanId",
    l.total_amount AS "context.loanAmount",
    l.due_date AS "context.dueDate"
FROM borrowers b
JOIN loans l ON l.borrower_id = b.id
WHERE l.status = 'overdue'

This will make loanAmount and dueDate available in your message templates via the context object.

Step 2: Create a Bulk Sender

A bulk sender defines:

  • Interaction Subject: The type of message (e.g., paymentDueDateReminder, loanOverdueFirstNotice)
  • Interaction Theme: The category of interaction (e.g., opsServicing, collections)
  • Interaction Channel: The delivery method (e.g., email, text, mail)

Note: Only mail, text, and email channels are compatible with the campaigns system.

Example: Create a Payment Reminder Bulk Sender

POST /api/campaign-workers/bulk-senders
Content-Type: application/json

{
  "interactionSubject": "paymentDueDateReminder",
  "interactionTheme": "opsServicing",
  "interactionChannel": "email",
}

Response

{
  "data": {
    "id": "BS-XXXX-XXXX",
    "interactionSubject": "paymentDueDateReminder",
    "interactionTheme": "opsServicing",
    "interactionChannel": "email",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}

Save the id field (e.g., BS-XXXX-XXXX) - you'll need it when creating the campaign.

Available Interaction Subjects

Some common interaction subjects that work well with bulk senders:

  • paymentDueDateReminder - Remind borrowers of upcoming payments
  • loanOverdueFirstNotice - First notice for overdue loans
  • loanOverdueSecondNotice - Second notice for overdue loans
  • autopayPaymentReminder - Remind borrowers of upcoming autopay payments
  • autopayEnableReminder - Encourage borrowers to enable autopay
  • loginFirstPaymentReminder - Remind borrowers who haven't logged in about their first payment
  • cardExpiresReminder - Notify borrowers about expiring payment cards

Each subject has specific query requirements and automatically calculated context variables.

Step 3: Create a Campaign

Now you'll create a campaign that ties your Redash query to your bulk sender.

Example: Create a Campaign

POST /api/campaigns
Content-Type: application/json

{
  "redashQueryUrl": "https://your-redash-domain.com/queries/123",
  "redashApiKey": "your-redash-api-key",
  "bulkSenderId": "BS-XXXX-XXXX",
  "externalId": "weekly-payment-reminders",
  "schedule": "P P * * mon"
}

Campaign Parameters

  • redashQueryUrl: The full URL to your Redash query (format: https://{DOMAIN}/queries/{QUERY_ID})
  • redashApiKey: Your Redash API key
  • bulkSenderId: The ID of the bulk sender created in Step 2
  • externalId: (Optional) Your own identifier for this campaign
  • schedule: (Optional) Cron schedule for automatic execution

Schedule Format

The schedule uses "Peachy crontab" format where P means "Peach decides":

  • Minute and hour fields must be P
  • Day, month, and day-of-week can be standard cron values

Examples:

  • P P * * mon - Every Monday
  • P P 1,15 * * - 1st and 15th of every month
  • P P * * wed - Every Wednesday
  • P P * 10 * - Every day in October

If schedule is null, the campaign must be run manually.

Response

{
  "data": {
    "id": "BC-XXXX-XXXX",
    "redashQueryUrl": "https://your-redash-domain.com/queries/123",
    "bulkSenderId": "BS-XXXX-XXXX",
    "externalId": "weekly-payment-reminders",
    "schedule": "P P * * mon",
    "createdAt": "2024-01-15T10:35:00Z"
  }
}

Step 4: Run a Campaign

If you didn't set a schedule, or want to run the campaign immediately, you can trigger it manually.

Manual Campaign Run

POST /api/campaigns/BC-XXXX-XXXX/runs
Content-Type: application/json

{}

Override Query Results (Optional)

For testing, you can override the Redash query with custom data:

POST /api/campaigns/BC-XXXX-XXXX/runs
Content-Type: application/json

{
  "queryResultsOverride": [
    {
      "borrowerId": "BO-YYYY-YYYY",
      "loanId": "LO-ZZZZ-ZZZZ"
    },
    {
      "borrowerId": "BO-AAAA-AAAA",
      "loanId": "LO-BBBB-BBBB"
    }
  ]
}

Response

{
  "data": {
    "id": "RN-XXXX-XXXX",
    "borrowerCampaignId": "BC-XXXX-XXXX",
    "status": "initializing",
    "availableFiles": []
  }
}

Step 5: Monitor Campaign Runs

Check the status of your campaign run:

GET /api/campaigns/BC-XXXX-XXXX/runs/RN-XXXX-XXXX

Run Statuses

  • initializing - Campaign run is being set up
  • processing - Campaign is actively running
  • success - Campaign completed successfully
  • failed - Campaign encountered an error

Download Campaign Results

Once a campaign run completes, you can download various files:

GET /api/campaigns/BC-XXXX-XXXX/runs/RN-XXXX-XXXX/download?file=all

Available files:

  • query_results.csv - Raw query results from Redash
  • campaign_input.json - Parsed query results used as input
  • contacts.csv - Exported contacts (if using contact exporter)
  • log.txt - Execution log

Use file=all to download all files as a ZIP, or specify a specific file.

Best Practices

1. Query Optimization

  • Keep your queries focused and efficient
  • Use appropriate WHERE clauses to limit results
  • Consider adding indexes on frequently queried columns

2. Testing

  • Always test with queryResultsOverride first using a small dataset
  • Verify message templates work correctly with your context variables
    • Campaign bulk send messages are sent with strictUndefined: true meaning there can be NO undefined variables or the send will fail. (This is not the default setting when using the /send endpoint.)
  • Check campaign run logs for any errors.
    • It's important to check the logs not just the status of the campaign run. This is because some or all of the message sends might fail even while the campaign run itself is considered a success.

3. Scheduling

  • Start with manual runs to verify everything works
  • Note that the schedule syntax is "crontab" like. You can specify a crontab except the first two parts must be P P this indicates that the specific time of execution on the given day is at Peach's discretion.

4. Context Variables

  • Use context.* columns in your query to pass custom data to templates
  • Be aware that some interaction subjects automatically calculate context variables
  • Ensure all required context variables are present or calculated

Troubleshooting

Campaign Run Fails

  1. Check the campaign run status and logs:
    GET /api/campaigns/{campaignId}/runs/{runId}
    GET /api/campaigns/{campaignId}/runs/{runId}/download?file=log.txt

Messages Not Sending

  1. Verify the bulk sender configuration:

    • Check that interactionSubject, interactionTheme, and interactionChannel are valid
    • Ensure message templates exist for the specified subject/theme/channel combination
  2. Check borrower eligibility:

    • Borrowers must have valid contact information for the specified channel
    • Compliance checks may prevent sending (Do Not Interact, frequency limits, etc.)

Query Results Issues

  1. Verify your Redash query:

    • Test the query directly in Redash
    • Ensure column names match exactly (case-sensitive)
    • Check that IDs are valid (either public IDs or internal integer IDs)
  2. Check query result format:

    • Minimum required: borrowerId column
    • Additional columns depend on the interaction subject
    • Use context.* prefix for custom context variables

Next steps