Built by SpreadRunBeta

Davis-Bacon WH-347 Certified Payroll Pre-Check

A certified payroll is a signed statement to the federal government, and a wrong one can cost you the money owed on the job and the right to bid on the next one. Check each week's payroll before you sign it: SpreadRun recomputes every row against the wage determination and explains every problem with its row, column, rule and source. Validate, then download the completed WH-347 ready to sign.

What a wrong payroll can cost

  • Withheld payments. The contracting agency can withhold contract payments to cover back wages, interest and other amounts owed, and can take them from your other federal or Davis-Bacon contracts too. Payments can also be suspended while payrolls or records are missing.
  • Overtime damages. On contracts covered by the Contract Work Hours and Safety Standards Act, unpaid overtime brings back wages plus liquidated damages of $33 for each worker for each day they worked over 40 hours in the week without overtime pay.
  • Debarment. A contractor found to have disregarded its obligations to workers is barred from federal and Davis-Bacon contracts for 3 years, and so are its responsible officers and the firms they have an interest in.
  • Falsification. Signing a Statement of Compliance that is not true can lead to civil or criminal prosecution under federal false statement and false claims laws.

Sources: 29 CFR 5.5, 5.9 and 5.12 and the WH-347 Statement of Compliance, linked at the bottom of this page.

Where this fits. The Department of Labor publishes Form WH-347 and its instructions for free, and using the form itself is optional: any format with the same information works. What the form does not do is check itself. SpreadRun works before the payroll is certified: an independent recomputation of every rate, fringe, overtime hour and total, with findings you can act on (a rule ID, the exact row and column, and the regulation or instruction behind it). Each report carries the date and a SHA-256 fingerprint of the exact file checked, so you can keep a record of what was checked before you signed. When the payroll passes, you can also download the completed WH-347: it is still the Department of Labor's form, filled from your validated data, with the Statement of Compliance left blank for your certifying official to check and sign. You sign it and file it. No software to install, no contract, and the test below needs no account.

A PASS does not mean the payroll complies with Davis-Bacon requirements. These are structural checks, not legal or compliance advice. The check uses the wage determination rates you send and cannot tell whether they are the right ones, whether workers are classified correctly, or whether fringe plans are bona fide.

Personal data. Certified payrolls name workers and carry identifying numbers and pay. Under the Terms, files sent to this check may contain that data: it is processed in memory only to produce the report and is not stored, and no value from your file is repeated in the report. You confirm you are permitted to share the file with SpreadRun as a service provider. If you ask for the completed WH-347, it is built from your values in memory and sent only to you, in the same response; it is not stored, logged or cached. Never send full Social Security numbers: certified payrolls must not include them, and the check flags any that look like one. The sample files on this page are invented.

Quick overtime math for one worker? Use the free Davis-Bacon overtime calculator.

What it checks

  • Required WH-347 fields. Project name and number, payroll number, contractor name and address, project location, wage determination number, week ending date, and every per-worker column of the form.
  • Classifications. Every labor classification on the payroll is on the wage determination you supplied.
  • Basic rates. The straight time rate paid is at least the basic hourly rate for the classification. Fringe payments cannot make up a shortfall here.
  • Fringe benefits. Plan credit (6B), cash in lieu (6C) and any cash wage above the basic rate together cover the fringe rate for every hour worked, as 29 CFR 5.31 allows. 6B and 6C match hours times their hourly amounts.
  • Overtime. No more than 40 straight time hours a week per worker, and overtime paid at no less than one and one-half times the basic rate. A rate under one and one-half times the rate actually paid is a warning.
  • Apprentices. Registered apprentice rows at their level's percentage of the journeyworker rate, the program's fringe (or the full fringe when the program is silent), and the program ratio on each day of this payroll.
  • Arithmetic. Daily hours add up to the weekly total, gross pay covers hours times rates, gross for all work is at least gross on this project, deductions add up, and net pay equals gross for all work minus deductions.
  • Identity. No full Social Security numbers, and one identifying number per worker entry.

Shortfalls and arithmetic errors are errors and make the report FAIL. Things that need a second look, like a gross amount that does not match either way of computing it, are warnings.

Who it's for

  • Contractors and subcontractors: check each week's payroll before the certifying official signs it.
  • Prime contractors: check subcontractor payrolls as they come in.
  • Payroll and construction software: run the check from your export, with a structured JSON report.
  • AI agents and automation: a plain REST endpoint with a file in and JSON out.

Not checked

  • Whether the rates you supplied are the right wage determination for the contract, location and dates. There is no live lookup.
  • Whether each worker's classification matches the work actually done.
  • Hours on other projects for the same contractor, which count toward 40 but are not on this payroll.
  • Apprentice registration, and the ratio across the contractor's whole workforce on site.
  • Whether fringe plans are bona fide, annualization, and approval of unfunded plans.
  • Whether deductions are permitted under 29 CFR part 3, and the signed Statement of Compliance.

Input and output

  1. Send

    An .xlsx workbook with Header, Payroll, Wage Determination and optional Apprenticeship sheets, or JSON with the header and the tables as CSV. One row per worker per classification, with daily straight time and overtime hours, as on the WH-347. Up to 4.4 MB.

  2. Recompute

    Every row against its classification's basic and fringe rates, every worker's week against the overtime rule, and every total against its parts.

  3. Report

    JSON with status (PASS, WARN or FAIL), findings (severity, ruleId, path such as /payroll/row[3]/st_rate, message, source), and counts of workers, rows, hours and apprentices. For a paid PASS, the completed WH-347 as a PDF, unsigned.

Every column, the JSON format and the full report schema are in the API docs. The sample workbook doubles as a template; its rates are invented.

Try it now

Free demo, no account: up to 512 KB per run, 10 runs a day. For full validations from this form, sign in and buy credits: $25.00 per completed report, packs from $50.

Payroll format
Sheets: Header, Payroll, Wage Determination, and Apprenticeship if you have apprentices. Start from the sample workbook.

Processed in memory and not stored. Reports never repeat names, IDs or amounts from your file.

Sample report
Synthetic payroll with planted problems
FAIL
Week ending 2026-09-267 workers8 rows252 hours3 apprentices15 errors3 warnings
SeverityRuleWhere and what
ErrorWH-APPR-PROGRAM/payroll/row[8]/apprentice_level
No apprenticeship program wage schedule was supplied for this classification and level, so the journeyworker rate on the wage determination applies.
ErrorWH-DEDUCTIONS-TOTAL/payroll/row[4]/total_deductions
Total deductions does not equal tax withholdings plus FICA plus other deductions.
ErrorWH-FRINGE-SHORT/payroll/row[3]
Wages, fringe benefit credit (6B) and cash in lieu of fringe benefits (6C) together are less than the basic hourly rate plus the fringe benefit rate owed for these hours (overtime premium on the basic rate only).
ErrorWH-FRINGE-SHORT/payroll/row[6]
Wages, fringe benefit credit (6B) and cash in lieu of fringe benefits (6C) together are less than the basic hourly rate plus the fringe benefit rate owed for these hours (overtime premium on the basic rate only).
ErrorWH-FRINGE-SHORT/payroll/row[8]
Wages, fringe benefit credit (6B) and cash in lieu of fringe benefits (6C) together are less than the basic hourly rate plus the fringe benefit rate owed for these hours (overtime premium on the basic rate only).
ErrorWH-GROSS-ALL-WORK/payroll/row[3]/gross_all_work
Gross amount earned for all work (7B) is less than the gross amount earned on this project (7A).
ErrorWH-HOURS-TOTAL/payroll/row[4]/total_hours
total_hours (column 5) does not equal the straight time and overtime hours entered for each day (column 4).
ErrorWH-ID-FULL-SSN/payroll/row[3]/worker_id
This identifying number looks like a full Social Security number. Certified payrolls must not include full SSNs; use the last four digits or another number specific to the worker.
ErrorWH-NET-PAY/payroll/row[1]/net_pay
Net pay (9) does not equal gross amount earned for all work (7B) minus total deductions (8).
ErrorWH-NET-PAY/payroll/row[4]/net_pay
Net pay (9) does not equal gross amount earned for all work (7B) minus total deductions (8).
ErrorWH-OT-HOURS/payroll/row[6]
More than 40 straight time hours in the week for this worker (all classification rows together). On contracts subject to the Contract Work Hours and Safety Standards Act, hours over 40 must be paid as overtime.
ErrorWH-RATE-BASE/payroll/row[3]/st_rate
The straight time rate is below the basic hourly rate required for this classification on the wage determination. Fringe benefit payments cannot make up a shortfall in the basic rate.
ErrorWH-RATE-BASE/payroll/row[8]/st_rate
The straight time rate is below the basic hourly rate required for this classification on the wage determination. Fringe benefit payments cannot make up a shortfall in the basic rate.
ErrorWH-RATE-OT-BASE/payroll/row[1]/ot_rate
The overtime rate is below one and one-half times the basic hourly rate on the wage determination.
ErrorWH-WD-CLASSIFICATION/payroll/row[5]/classification
This labor classification is not in the wage determination table. Workers must be paid the rate for the classification of work actually performed; a classification missing from the wage determination needs a conformance request through the contracting officer.
WarningWH-APPR-RATIO/payroll/row[2]
On 5 days this payroll shows more apprentices in this classification than the program ratio allows for the journeyworkers on it. Apprentices over the ratio must be paid the full journeyworker rate. Only this payroll is counted.
WarningWH-GROSS-MISMATCH/payroll/row[1]/gross_project
Gross amount earned on this project (7A) does not equal hours times the rates paid, with or without the payment in lieu of fringe benefits (6C). Check for a missing or extra amount.
WarningWH-GROSS-MISMATCH/payroll/row[3]/gross_project
Gross amount earned on this project (7A) does not equal hours times the rates paid, with or without the payment in lieu of fringe benefits (6C). Check for a missing or extra amount.

Pricing

$25.00 per completed report. One weekly payroll, one full report, and for a payroll that passes, the completed WH-347 PDF at no extra charge.

  • Billed when a report is produced, PASS, WARN or FAIL. Invalid input is never billed: a PDF, a workbook missing a required sheet, JSON without the payroll or the rates.
  • Paid from the same prepaid credits as every SpreadRun API, in $5, $20, $50 or $100 packs. A $50 pack covers 2 weekly checks. Credits never expire. All pricing
  • Running payrolls for many projects every week? Talk to us first so we can tell you honestly whether this fits.

Call it from code

Columns, the JSON format, rule IDs, error codes and limits are in the API docs.

curl -X POST "https://www.spreadrun.com/api/v1/wh347-payroll-precheck" \
  -H "Authorization: Bearer $SPREADRUN_API_KEY" \
  -H "Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" \
  --data-binary @payroll_week_06.xlsx

Questions

The WH-347 form is free from the Department of Labor. Why pay for this?

The form and its instructions are free, and you should use them, or any format with the same information. What the form does not do is check itself. SpreadRun recomputes every row against the wage determination rates and tells you, before you sign the Statement of Compliance, which rows are short, which totals do not add up and where. It runs from this page or from your payroll system through the API, in seconds, every week.

Does a PASS mean the payroll complies with Davis-Bacon?

No. A PASS means the payroll passed the checks listed on this page against the rates you supplied. It cannot tell whether those are the right rates for the contract, whether workers are classified correctly for the work they did, or whether fringe benefit plans are bona fide. These are structural checks, not legal or compliance advice.

Where do the wage determination rates come from?

From you. Copy the basic hourly rate and fringe benefit rate for each classification from the wage determination in your contract (published on SAM.gov) into the Wage Determination sheet or table. SpreadRun does not look rates up: there is no stable public interface for wage determinations that we could verify, and a wrong automatic match would be worse than none. The report checks the payroll against exactly the rates you send.

Which file formats work?

An .xlsx workbook with sheets named Header, Payroll, Wage Determination and, if you have apprentices, Apprenticeship. Or, through the API, a JSON object with the header fields and the three tables as CSV text. Download the sample workbook on this page to start from the right columns. PDF payrolls cannot be read.

How is overtime checked?

On contracts subject to the Contract Work Hours and Safety Standards Act (generally over $100,000), hours over 40 in the workweek must be paid at one and one-half times the basic rate. The check flags more than 40 straight time hours for a worker across all rows, and an overtime rate below one and one-half times the wage determination's basic rate. Fringe benefits and cash in lieu of them are left out of the overtime calculation, as 29 CFR 5.32 allows. If the contract is not subject to that Act, set cwhssa to no.

How are fringe benefits checked?

The way 29 CFR 5.31 describes: the basic hourly rate must be paid in cash, and the fringe benefit rate can be met by plan contributions (column 6B), cash in lieu of benefits (column 6C), cash wages above the basic rate, or a mix. A row fails when everything paid for its hours comes to less than the basic rate plus the fringe rate owed. Fringe credit can never make up a basic rate below the wage determination.

What about apprentices?

List each registered apprenticeship program's wage schedule in the Apprenticeship sheet: classification, level, wage percentage of the journeyworker rate, fringe percentage (leave it blank if the program does not specify, and the full fringe rate applies) and the ratio. Apprentice rows are checked against their level's rate, and each day's count of apprentices against journeyworkers in the same classification on this payroll. An apprentice with no program schedule must be paid the journeyworker rate.

Can SpreadRun fill in the WH-347 for me?

Yes, once the payroll passes. Signed in with credits (or through the API with ?form=pdf), a PASS comes back with the completed DOL Form WH-347, January 2025 revision: page 1 with every worker, hour, rate, deduction and total from your file (a new page 1 for every 8 rows), and page 2 with the project details, apprenticeship programs and hourly fringe credits. The fringe plan names and numbers, the OA or SAA boxes, the Statement of Compliance boxes and the signature are left for your certifying official. A payroll with findings gets no form: fix the findings and run it again. The form is included in the report price.

Is the payroll data stored?

No. Files are processed in memory for the length of the request and are not stored or shared. Certified payrolls name workers and carry identifying numbers and pay, which is personal data. Findings name the row, the column, the rule and the problem, never a value from your file. For billing and usage we log the time, endpoint, result status, upload size and duration, never the file contents.

When is a run charged?

When the check finishes and returns a report, whether it says PASS, WARN or FAIL: $25.00 per report. Requests rejected before a report exists are free: a PDF, a workbook without the required sheets, JSON without the payroll or wage determination table, unreadable CSV.

Sources

SpreadRun is not affiliated with or endorsed by the Department of Labor. Where this check and the regulations or the wage determination differ, the regulations and the wage determination control.

More validators: PBJ Staffing Data Pre-Submission QA | the full catalog