Daily Bullhorn placements to billing sheet and Slack

Every weekday at 6pm Eastern, log new Bullhorn placements into a shared billing tracker and post a one-line summary to your finance Slack channel.

Deterministic Code
BullhornGoogle SheetsSlackFinanceOperationsData SyncDaily DigestsNotifications & Alerts

Build a code-based workflow that runs every weekday at 6pm Eastern and logs the day's new Bullhorn placements to a shared Google Sheets billing tracker, then posts a one-line summary to our finance Slack channel. This is a deterministic pipeline with fixed steps, no drafting or judgement.

Trigger: cron, weekdays (Monday through Friday) at 18:00 America/New_York.

Step 1. Use Bullhorn Query Entities (JPQL) against the Placement entity to find every placement where dateAdded is greater than or equal to the start of today in Eastern time. Use the JPQL query endpoint, not Search Entities, because Placement filtering by dateAdded is structured. Request only the placement id field here; we will fetch the full record in step 2. Page through results until all matching placements are returned.

Step 2. For each placement id from step 1, call Bullhorn Get Entity by ID on the Placement entity and request these fields: candidate(firstName,lastName), clientCorporation(name), jobOrder(title), dateBegin, payRate, billRate, fee, employmentType, and id. Use nested field selection so we get the candidate name, client corporation name, and job title in a single call.

Step 3. For each placement, append one row to the shared Google Sheets billing tracker using Append Values. The sheet id and tab name should be configurable. The column order, which must stay stable because finance already uses it, is: Date Added, Candidate Name, Client Corporation, Job Title, Start Date (dateBegin), Bill Rate, Pay Rate, Fee, Employment Type, Placement ID. Format Bullhorn epoch-millisecond timestamps as YYYY-MM-DD in the sheet.

Step 4. Compute a one-line summary: count the placements and sum the weekly bill value, where weekly bill value per placement is billRate multiplied by 40 (assume a 40-hour week for hourly placements; for salaried placements where billRate is a weekly amount, use it as-is). Then use Slack Send a Message to post to the #finance-ops channel with the text "N new placements today, $X total weekly bill value" and include a clickable link to the billing tracker spreadsheet. Format the dollar total with a thousands separator and no decimals.

If there are zero placements for the day, still post a Slack message saying "0 new placements today" so finance knows the sweep ran. Do not append empty rows to the spreadsheet on zero-placement days.

Make the channel name, spreadsheet id, tab name, time zone, and trigger time configurable so other teams can reuse this pattern.

Additional information

What does this prompt do?
  • Sweeps Bullhorn at the end of each business day for placements that were created or activated that day.
  • Appends one row per placement to your shared billing tracker in Google Sheets, with candidate name, client, role, rates, fee, and start date.
  • Posts a one-line summary to your finance Slack channel showing how many placements landed and the total weekly bill value.
  • Runs automatically on weekdays at 6pm Eastern, so finance never has to chase recruiters for an end-of-day count.
What do I need to use this?
  • A Bullhorn account with REST API access that can read placement records.
  • A Google account with edit access to the shared billing tracker spreadsheet, with a header row that matches the columns you want logged.
  • A Slack workspace and a finance channel where the daily summary should land.
How can I customize it?
  • Change the time or which days it runs, for example move it to 7pm or include Saturdays during peak billing weeks.
  • Swap the Slack channel, edit the wording of the summary, or include a link straight to the day's new rows.
  • Adjust which placement fields land in the spreadsheet, or add extra columns like recruiter, branch, or department.

Frequently asked questions

What counts as a new placement?
We pull every placement in Bullhorn that was created or activated since the start of the current day, in your local time zone.
Will this work if my finance team uses a different sheet layout?
Yes. The column layout is configurable when you set the workflow up. Make sure your spreadsheet's header row matches the fields you want logged and the workflow will fill them in the same order every day.
Can I run it more than once a day or only on certain days?
Yes. The schedule is just a setting. You can run it twice daily, only on Fridays, or anything in between to match your billing cadence.
What happens on a day with no new placements?
The Slack message will report zero placements so finance still knows the sweep ran. You can also configure it to skip the post on empty days.
Does it overwrite the billing tracker?
No. Each placement is appended as a new row beneath what is already there, so the sheet grows over time and your historical record stays intact.

Stop chasing recruiters for end-of-day placement counts.

Connect Bullhorn, Google Sheets, and Slack once, and Geni logs every new placement to your billing tracker at 6pm every weekday.