# Integration Scripts

<details>
<summary><strong>Sync revenue totals to HubSpot CRM</strong> (read from Kick, write to HubSpot)</summary>

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 '  
  [.[] | select(.amount > 0)] | 
  group_by(.counterparty) |  
  map({client: .[0].counterparty, revenue: (map(.amount) | add)})
' | 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

**What It Outputs**

* Updates `monthly_revenue` on matching HubSpot companies
* Console output for each client processed

</details>

<details>
<summary><strong>Export transactions to a data warehouse</strong> (read from Kick, write to database)</summary>

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 "
    COPY transactions (id, date, amount, counterparty, category)
    FROM STDIN WITH CSV
  "

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

**What It Outputs**

* Rows loaded into the `transactions` table
* Console confirmation

</details>

<details>
<summary><strong>Export project expenses to Notion</strong> (read from Kick, write to Notion)</summary>

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\" } }] }
      }
    }"
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

**What It Outputs**

* One Notion page per matching expense
* Console output for each row created

</details>

<details>
<summary><strong>Send weekly expense summary to Slack</strong> (read from Kick, write to Slack)</summary>

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 '  
  group_by(.category) |  
  map({  
    category: (.[0].category // "Uncategorized"),
    total: (map(.amount | fabs) | add)  
  }) |  
  sort_by(.total) | reverse | .[0:3] |  
  map("• \.category: $\.total") |  
  join("\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.

</details>
