Skip to main content
This guide covers the bill pay rules API — creating rules, understanding the condition AST structure, configuring actions, and managing rule lifecycle.

Endpoints

MethodEndpointPurpose
GET/api/v2/company/{id}/bill-pay/rules/List all rules
POST/api/v2/company/{id}/bill-pay/rules/Create a rule
GET/api/v2/company/{id}/bill-pay/rules/{id}/Get rule detail
PATCH/api/v2/company/{id}/bill-pay/rules/{id}/Update a rule
DELETE/api/v2/company/{id}/bill-pay/rules/{id}/Delete a rule
GET/api/v2/company/{id}/bill-pay/destinations/List destinations
POST/api/v2/company/{id}/bill-pay/destinations/Create a destination
GET/api/v2/company/{id}/bill-pay/decisions/List routing decisions
GET/api/v2/company/{id}/bill-pay/cycles/List bill pay cycles
GET/api/v2/company/{id}/bill-pay/funding-summary/Funding overview

Rule structure

A rule consists of:
  • name — human-readable label
  • description — optional explanation of the rule’s purpose
  • phase — either ROUTING or GL_CODING
  • isActive — whether the rule is currently being evaluated
  • priority — evaluation order (lower numbers evaluate first)
  • conditionAst — the condition tree (see below)
  • actions — array of action objects

Condition AST

Conditions are expressed as an abstract syntax tree (AST) with four node types:

COMPARE node

Tests a single field against a value:
{
  "type": "COMPARE",
  "field": "bill.totalCharges",
  "operator": "GT",
  "value": "5000"
}

AND node

All children must match:
{
  "type": "AND",
  "children": [
    { "type": "COMPARE", "field": "bill.datasourceType", "operator": "EQ", "value": "ELECTRICITY" },
    { "type": "COMPARE", "field": "bill.totalCharges", "operator": "GT", "value": "1000" }
  ]
}

OR node

Any child can match:
{
  "type": "OR",
  "children": [
    { "type": "COMPARE", "field": "site.id", "operator": "EQ", "value": "uuid-1" },
    { "type": "COMPARE", "field": "site.id", "operator": "EQ", "value": "uuid-2" }
  ]
}

NOT node

Inverts the child:
{
  "type": "NOT",
  "child": { "type": "COMPARE", "field": "bill.isFlagged", "operator": "EQ", "value": "true" }
}

Condition fields

FieldValue typeDescription
bill.datasourceTypestring (enum)Commodity: ELECTRICITY, GAS, WATER, WASTE, FUEL, SOLAR, DISTRICT
bill.totalChargesdecimalTotal bill amount
bill.isFlaggedbooleanWhether the bill is flagged
bill.datasourceUUIDSpecific utility provider
bill.chargesUnitsstringCurrency code (USD, CAD, EUR, etc.)
site.idUUIDSpecific site
site.tagsstring (multi)Site tags
site.locationstring (multi)Site location
account.idUUIDSpecific account
workflow.idUUIDSpecific connection

Operators

OperatorApplies toDescription
EQAllEquals
NEQAllDoes not equal
INEnum, UUIDIs one of (array value)
NOT_INEnum, UUIDIs not one of (array value)
CONTAINSStringContains substring
NOT_CONTAINSStringDoes not contain substring
GTDecimal, DateGreater than
GTEDecimal, DateGreater than or equal
LTDecimal, DateLess than
LTEDecimal, DateLess than or equal
BETWEENDecimal, DateBetween two values (array of [min, max])
IS_NULLAllField is empty (no value argument)
IS_NOT_NULLAllField has a value (no value argument)

Action types

Routing rule actions

{
  "type": "FORWARD_EMAIL",
  "destinationId": "uuid-of-email-destination"
}

GL coding rule actions

{
  "type": "ASSIGN_GL_CODE",
  "glCode": "6200",
  "glCodeName": "Utilities - Water"
}

Creating a rule (example)

curl -X POST \
  https://api.nectarclimate.com/api/v2/company/{company_id}/bill-pay/rules/ \
  -H "Authorization: Api-Key YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Forward large electricity bills to CFO",
    "description": "Bills over $10k need CFO review before AP processes them",
    "phase": "ROUTING",
    "isActive": true,
    "conditionAst": {
      "type": "AND",
      "children": [
        {
          "type": "COMPARE",
          "field": "bill.datasourceType",
          "operator": "EQ",
          "value": "ELECTRICITY"
        },
        {
          "type": "COMPARE",
          "field": "bill.totalCharges",
          "operator": "GT",
          "value": "10000"
        }
      ]
    },
    "actions": [
      {
        "type": "FORWARD_EMAIL",
        "destinationId": "uuid-of-cfo-destination"
      }
    ]
  }'

Rule evaluation behavior

  • Rules are evaluated in priority order (lower number = higher priority)
  • All matching rules fire — evaluation doesn’t stop at the first match
  • Actions are deduplicated by destination — if two rules route to the same destination, delivery happens only once
  • GL coding rules evaluate before routing rules in the same pass
  • A rule with no conditions matches every bill (acts as a catch-all)

Decisions (evaluation results)

After evaluation, each bill gets a decision record accessible via the decisions endpoint. The decision includes:
  • Which rules were evaluated
  • Which rules matched (with full condition trace)
  • What actions fired and their delivery status (PENDING, APPLIED, DELIVERED, FAILED)