> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dualentry.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Automate Bill Status Checks in CI/CD

> Use the DualEntry CLI with an API key to pull posted bills as JSON in a CI/CD pipeline, then pipe the results to jq or a scheduled job.

This workflow shows developers how to build automation around accounts payable. For example, you can build a scheduled job that checks for new posted bills and sends a notification to Slack, or a pipeline that reconciles bill data against another system.

## Prerequisites

Before you start, complete the steps in the [CLI Quickstart](/developers/guides/cli/quickstart):

* The CLI is installed.
* You have read access to bills.

## Steps

**Step 1 - Set up authentication for your pipeline:**

In your CI/CD environment (GitHub Actions, Jenkins, etc.), add `X_API_KEY` as a secret. The CLI uses this automatically when the environment variable is set; no browser-based login required.

```bash theme={null}
export X_API_KEY="$DUALENTRY_API_KEY"  # reference your CI/CD secret
```

**Step 2 - Pull posted bills as JSON:**

```bash theme={null}
dualentry bills list --status posted --format json
```

The `--status` and `--format` flags are confirmed on `bills`. JSON output makes it straightforward to parse programmatically.

**Step 3 - Pipe into `jq` or another tool:**

A `list` command returns an object, not a bare array. The shape is `{items: [...], count: N}`, where `count` is the total available rather than the number returned on this page. Reach into `.items[]` to iterate the records:

```bash theme={null}
dualentry bills list --status posted --format json | jq '.items[] | {id, vendor: .vendor_name, amount: .amount_due, due_date: .due_date}'
```

Inspect the raw output once to confirm the exact field names available on your version, then build your filter against those keys. Piping to `jq '.[]'` instead of `.items[]` iterates the object's values rather than the records, which yields the array and the count as two results rather than one record per line.

**Step 4 - Add to a scheduled job:**

Wire the same commands into a scheduled CI workflow. The example below runs each weekday morning in GitHub Actions:

```yaml theme={null}
name: Check posted bills
on:
  schedule:
    - cron: '0 9 * * 1-5'  # weekdays at 9am

jobs:
  check-bills:
    runs-on: ubuntu-latest
    steps:
      - name: Install DualEntry CLI
        run: curl -fsSL https://raw.githubusercontent.com/dualentry/dualentry-cli/main/install.sh | sh

      - name: List posted bills
        env:
          X_API_KEY: ${{ secrets.DUALENTRY_API_KEY }}
        run: dualentry bills list --status posted --format json > bills.json

      - name: Process results
        run: |
          # your notification or reconciliation logic here
          jq '.count' bills.json
```

<Warning>
  The install script method shown here requires Python 3.11+ on the CI runner. Add a setup step (e.g., `actions/setup-python` with `python-version: '3.11'`) if your runner image doesn't include it.
</Warning>

**Result:** A scheduled CI/CD job runs on the cadence you choose, pulls posted bills as JSON, and hands them to your notification or reconciliation logic.

Note that `jq '.count'` reports the total matching the filter, which can exceed the records in the file. Add `--all` to the list command if the job needs every record rather than the first page.

## Tips

* **Use `--format json` for anything automated**: table output is great for humans but brittle for scripts.
* **The CLI is read-heavy today**: while `create` and `update` exist, the highest-value use cases right now tend to be listing, filtering, and exporting data.

## Related

* [How to Review Outstanding Invoices with the CLI](./how-to-review-outstanding-invoices)
* [CLI Reference](./reference)
