**Sync revenue totals to HubSpot CRM** (read from Kick, write to HubSpot)

To push inflow totals by counterparty into HubSpot, aggregate transaction JSON from Kick, search for each company, then update it.

### The Script

```bash
#!/bin/bash
# sync-revenue-to-hubspot.sh

WORKSPACE_ID="<workspace-id>"
HUBSPOT_API_KEY="your-hubspot-api-key"
SINCE="2026-01-01"
UNTIL="2026-01-31"

kick --workspace "$WORKSPACE_ID" transactions find \
  --since "$SINCE" \
  --until "$UNTIL" \
  --fields amount,counterparty \
  --output json | \
jq -c '\n  [.[] | select(.amount > 0)] |\n  group_by(.counterparty) |\n  map({client: .[0].counterparty, revenue: (map(.amount) | add)})\n' | jq -c '.[]' | while IFS= read -r row; do
  client=$(echo "$row" | jq -r '.client')
  revenue=$(echo "$row" | jq -r '.revenue')

echo "Updating HubSpot for $client: $revenue"

company_id=$(curl -s -X POST "https://api.hubapi.com/crm/v3/objects/companies/search" \
    -H "Authorization: Bearer $HUBSPOT_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"filterGroups\":[{\"filters\":[{\"propertyName\":\"name\",\"operator\":\"EQ\",\"value\":\"$client\"}]}]}" \
    | jq -r '.results[0].id // empty')

if [ -z "$company_id" ]; then
    echo "No HubSpot company found for $client"
    continue
  fi

curl -s -X PATCH "https://api.hubapi.com/crm/v3/objects/companies/${company_id}" \
    -H "Authorization: Bearer $HUBSPOT_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\n      \"properties\": {\n        \"monthly_revenue\": \"$revenue\",\n        \"last_revenue_update\": \"$(date -I)\"\n      }\n    }"
done

echo "HubSpot revenue sync finished"
```

### How to Customize

- Match on a custom HubSpot property instead of `name`
- Add error handling and retry logic around the curl calls
- Filter inflows to specific categories in the `jq` step

---

**Export transactions to a data warehouse** (read from Kick, write to database)

To load transaction rows into PostgreSQL, export JSON and stream CSV into `COPY`.

### The Script

```bash
#!/bin/bash
# export-to-warehouse.sh

WORKSPACE_ID="<workspace-id>"
DB_HOST="your-db-host"
DB_NAME="analytics"
DB_USER="etl_user"
SINCE="2026-01-01"

kick --workspace "$WORKSPACE_ID" transactions find \
  --since "$SINCE" \
  --fields id,date,amount,counterparty,category \
  --output json \
  > /tmp/kick-transactions.json

jq -r '.[] | [.id, .date, .amount, .counterparty, (.category // "null")] | @csv' /tmp/kick-transactions.json | \
  psql -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" -c "\n    COPY transactions (id, date, amount, counterparty, category)\n    FROM STDIN WITH CSV\n  "

echo "Transactions loaded to warehouse"
```

### How to Customize

- Track the last loaded date and pass it to `--since` for incremental loads
- Page with `--cursor` when you exceed the default limit

---

**Export project expenses to Notion** (read from Kick, write to Notion)

To mirror expense rows into a Notion database, filter transactions by category in `jq` and create one page per row.

### The Script

```bash
#!/bin/bash
# export-to-notion.sh

WORKSPACE_ID="<workspace-id>"
NOTION_API_KEY="your-notion-api-key"
DATABASE_ID="your-notion-database-id"
CATEGORY_NAME="Marketing"
SINCE="2026-01-01"
UNTIL="2026-03-31"

kick --workspace "$WORKSPACE_ID" transactions find \
  --since "$SINCE" \
  --until "$UNTIL" \
  --fields date,amount,counterparty,category,memo \
  --output json | \
jq -c --arg cat "$CATEGORY_NAME" '.[] | select(.amount < 0 and .category == $cat)' | \
while IFS= read -r txn; do
  date=$(echo "$txn" | jq -r '.date')
  amount=$(echo "$txn" | jq -r '.amount | fabs')
  category=$(echo "$txn" | jq -r '.category')
  counterparty=$(echo "$txn" | jq -r '.counterparty')
  memo=$(echo "$txn" | jq -r '.memo // """)

echo "Adding $counterparty ($amount) to Notion"

curl -s -X POST "https://api.notion.com/v1/pages" \
    -H "Authorization: Bearer $NOTION_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Notion-Version: 2022-06-28" \
    -d "{\n      \"parent\": { \"database_id\": \"$DATABASE_ID\" },\n      \"properties\": {\n        \"Date\": { \"date\": { \"start\": \"$date\" } },\n        \"Vendor\": { \"title\": [{ \"text\": { \"content\": \"$counterparty\" } }] },\n        \"Category\": { \"select\": { \"name\": \"$category\" } },\n        \"Amount\": { \"number\": $amount },\n        \"Notes\": { \"rich_text\": [{ \"text\": { \"content\": \"$memo\" } }] }\n      }\n    }"
done

echo "Project expenses exported to Notion"
```

### How to Customize

- Change `CATEGORY_NAME` or filter on counterparty instead
- Map property names to match your Notion database schema

---

**Send weekly expense summary to Slack** (read from Kick, write to Slack)

To post last week's spend and top categories to a channel, aggregate transaction JSON and call a webhook.

### The Script

```bash
#!/bin/bash
# weekly-expense-summary.sh

WORKSPACE_ID="<workspace-id>"
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
SINCE="$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d '7 days ago' +%Y-%m-%d)"
UNTIL="$(date +%Y-%m-%d)"

expenses=$(kick --workspace "$WORKSPACE_ID" transactions find \
  --since "$SINCE" \
  --until "$UNTIL" \
  --fields amount,category \
  --output json \
  | jq '[.[] | select(.amount < 0)]')

total=$(echo "$expenses" | jq '[.[].amount] | add | fabs')

top_categories=$(echo "$expenses" | jq -r '\n  group_by(.category) |\n  map({\n    category: (.[0].category // "Uncategorized"),\n    total: (map(.amount | fabs) | add)\n  }) |\n  sort_by(.total) | reverse | .[0:3] |\n  map("• \(.category): $\(.total)") |\n  join("\n")\n')

message="*Weekly expense summary*\n*$SINCE to $UNTIL*\n\n*Total expenses:* \$$total\n\n*Top categories:*\n$top_categories\n\n<https://app.kick.co/transactions|View in Kick>"

curl -X POST "$WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"$message\"}"

echo "Weekly summary sent to Slack"
```

### How to Customize

- Change the date window for daily or monthly summaries
- Add entity-scoped review in Kick before running the export

---

### What It Outputs

- Slack message with total expenses and top three categories.
