> For the complete documentation index, see [llms.txt](https://docs.kick.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kick.co/ai/cli/cli-use-case-library/integration-scripts.md).

# 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 "{
      \"properties\": {
        \"monthly_revenue\": \"$revenue\",
        \"last_revenue_update\": \"$(date -I)\"
      }
    }"
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 "{
      \"parent\": { \"database_id\": \"$DATABASE_ID\" },
      \"properties\": {
        \"Date\": { \"date\": { \"start\": \"$date\" } },
        \"Vendor\": { \"title\": [{ \"text\": { \"content\": \"$counterparty\" } }] },
        \"Category\": { \"select\": { \"name\": \"$category\" } },
        \"Amount\": { \"number\": $amount },
        \"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>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kick.co/ai/cli/cli-use-case-library/integration-scripts.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
