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

# Business Development

> Track partnerships, funding, and product updates to find opportunities

## Overview

BD teams need early signals on partnerships, funding rounds, and product launches. Shoal's radar and signal endpoints surface these events automatically, ranked by significance — so you can act on opportunities before they're widely known.

### Deliver Alerts Where Your Team Works

<CardGroup cols={2}>
  <Card title="Slack" icon="slack" href="/integrations/slack">
    Real-time radar and signal cards in your BD channel, plus `/shoal brief` slash commands.
  </Card>

  <Card title="Telegram" icon="telegram" href="/integrations/telegram">
    Daily digest of top signal events ranked by score — perfect for mobile-first teams.
  </Card>
</CardGroup>

<Frame>
  <img src="https://mintcdn.com/shoalresearch/kPKbliFQYCFjQvCO/images/slack-integration.svg?fit=max&auto=format&n=kPKbliFQYCFjQvCO&q=85&s=6febacd9eaf5aa78f78d8452024bea81" alt="Shoal Intelligence Slack integration showing radar and signal event cards in a BD channel" width="1512" height="947" data-path="images/slack-integration.svg" />
</Frame>

<Note>
  You'll need an API key to follow along. See the [Quickstart](/quickstart) guide to create one.
</Note>

## Endpoints Used

| Endpoint                                                                                    | Purpose                               | Reference                                                 |
| ------------------------------------------------------------------------------------------- | ------------------------------------- | --------------------------------------------------------- |
| [`/v1/radar/byCategory`](/api-reference/radar/by-category)                                  | Partnership & acquisition events      | [Docs](/api-reference/radar/by-category)                  |
| [`/v1/signal/top`](/api-reference/signal/get-top)                                           | Highest-impact events across all orgs | [Docs](/api-reference/signal/get-top)                     |
| [`/v1/brief/batch`](/api-reference/brief/batch)                                             | Combined view for a watchlist of orgs | [Docs](/api-reference/brief/batch)                        |
| [`/v1/organizations/byOrganizationName`](/api-reference/organizations/by-organization-name) | Look up org by name                   | [Docs](/api-reference/organizations/by-organization-name) |

## Workflow

### Step 1: Build a Watchlist

Search for organizations by name and collect their IDs into a watchlist.

```bash cURL theme={null}
curl "https://api.shoal.xyz/v1/organizations/byOrganizationName?name=Chainlink" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```python Python theme={null}
import os, requests

API_KEY = os.environ.get("SHOAL_API_KEY", "YOUR_API_KEY")
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# Resolve org names to IDs
watchlist_names = ["Chainlink", "Arbitrum", "Aave", "Lido"]
watchlist_ids = []

for name in watchlist_names:
    r = requests.get(
        "https://api.shoal.xyz/v1/organizations/byOrganizationName",
        headers=HEADERS,
        params={"name": name},
    )
    data = r.json()["data"]
    if data:
        watchlist_ids.append(str(data[0]["id"]))
        print(f"{name} -> ID {data[0]['id']}")

print(f"Watchlist IDs: {','.join(watchlist_ids)}")
```

```javascript JavaScript theme={null}
const API_KEY = process.env.SHOAL_API_KEY || 'YOUR_API_KEY';
const HEADERS = { Authorization: `Bearer ${API_KEY}` };

const watchlistNames = ['Chainlink', 'Arbitrum', 'Aave', 'Lido'];
const watchlistIds = [];

for (const name of watchlistNames) {
  const res = await fetch(
    `https://api.shoal.xyz/v1/organizations/byOrganizationName?name=${encodeURIComponent(name)}`,
    { headers: HEADERS }
  );
  const { data } = await res.json();
  if (data.length > 0) {
    watchlistIds.push(data[0].id);
    console.log(`${name} -> ID ${data[0].id}`);
  }
}

console.log(`Watchlist IDs: ${watchlistIds.join(',')}`);
```

### Step 2: Poll for BD-Relevant Events

Call the radar category endpoints on a schedule with the `since` parameter to get only new events.

```bash cURL theme={null}
# Partnership events in the last 24 hours
SINCE=$(date -u -v-24H +"%Y-%m-%dT%H:%M:%SZ")  # macOS
# SINCE=$(date -u -d '24 hours ago' +"%Y-%m-%dT%H:%M:%SZ")  # Linux

curl "https://api.shoal.xyz/v1/radar/byCategory?category=partnership&since=$SINCE" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Funding rounds
curl "https://api.shoal.xyz/v1/radar/byCategory?category=funding&since=$SINCE" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```python Python theme={null}
import time
from datetime import datetime, timedelta, timezone

cursor = (datetime.now(timezone.utc) - timedelta(hours=24)).isoformat()

while True:
    # Check partnership events
    partnerships = requests.get(
        "https://api.shoal.xyz/v1/radar/byCategory",
        headers=HEADERS,
        params={"category": "partnership", "since": cursor},
    ).json()["data"]

    # Check funding events
    funding = requests.get(
        "https://api.shoal.xyz/v1/radar/byCategory",
        headers=HEADERS,
        params={"category": "funding", "since": cursor},
    ).json()["data"]

    for event in partnerships + funding:
        print(f"[{event['eventCategory']}] {event['title']}")

    if partnerships or funding:
        all_events = partnerships + funding
        cursor = max(e["latestPostTimestamp"] for e in all_events)

    time.sleep(900)  # Poll every 15 minutes
```

```javascript JavaScript theme={null}
let cursor = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();

async function pollBDEvents() {
  const categories = ['partnership', 'funding'];

  for (const category of categories) {
    const res = await fetch(
      `https://api.shoal.xyz/v1/radar/byCategory?category=${category}&since=${cursor}`,
      { headers: HEADERS }
    );
    const { data } = await res.json();
    for (const event of data) {
      console.log(`[${event.eventCategory}] ${event.title}`);
    }
    if (data.length > 0) {
      const latest = data[0].createdAt;
      if (latest > cursor) cursor = latest;
    }
  }
}

setInterval(pollBDEvents, 15 * 60 * 1000); // Poll every 15 minutes
```

### Step 3: Get a Daily Briefing

Use `/v1/brief/batch` with your watchlist IDs for a single-call portfolio update when batch brief is available on your plan.

```bash cURL theme={null}
# Use the IDs returned from Step 1 (e.g. from byOrganizationName lookups)
SINCE=$(date -u -v-24H +"%Y-%m-%dT%H:%M:%SZ")  # macOS
# SINCE=$(date -u -d '24 hours ago' +"%Y-%m-%dT%H:%M:%SZ")  # Linux

curl "https://api.shoal.xyz/v1/brief/batch?ids=YOUR_ORG_IDS&since=$SINCE&compact=true" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```python Python theme={null}
ids = ",".join(watchlist_ids)
since = (datetime.now(timezone.utc) - timedelta(hours=24)).isoformat()

r = requests.get(
    "https://api.shoal.xyz/v1/brief/batch",
    headers=HEADERS,
    params={"ids": ids, "since": since, "compact": "true"},
)

data = r.json()
for org in data["organizations"]:
    radar_count = org["counts"]["radar"]
    signal_count = org["counts"]["signal"]
    if radar_count > 0 or signal_count > 0:
        print(f"{org['label']}: {radar_count} radar, {signal_count} signals")
        for event in org.get("radar", []):
            print(f"  [{event['eventCategory']}] {event['title']}")
```

```javascript JavaScript theme={null}
const ids = watchlistIds.join(',');
const since = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();

const briefRes = await fetch(
  `https://api.shoal.xyz/v1/brief/batch?ids=${ids}&since=${since}&compact=true`,
  { headers: HEADERS }
);

const briefData = await briefRes.json();
for (const org of briefData.organizations) {
  const { radar, signal } = org.counts;
  if (radar > 0 || signal > 0) {
    console.log(`${org.label}: ${radar} radar, ${signal} signals`);
    for (const event of org.radar || []) {
      console.log(`  [${event.eventCategory}] ${event.title}`);
    }
  }
}
```

## Example Output

The [`/v1/brief/batch`](/api-reference/brief/batch) response groups events by organization. See the [full schema](/api-reference/brief/batch) for all available fields.

```json theme={null}
{
  "organizations": [
    {
      "id": 42,
      "label": "Chainlink",
      "counts": { "radar": 2, "signal": 5 },
      "radar": [
        {
          "eventCategory": "partnership",
          "title": "Chainlink CCIP integration with major TradFi institution",
          "signal": 9,
          "latestPostTimestamp": "2026-03-09T14:22:00Z"
        },
        {
          "eventCategory": "funding",
          "title": "Chainlink ecosystem fund announces new cohort",
          "signal": 7,
          "latestPostTimestamp": "2026-03-09T09:15:00Z"
        }
      ]
    }
  ],
  "next_cursor": null
}
```

## Lead Enrichment

Enrich your CRM contacts with Shoal intelligence before outreach — match company names to tracked organizations and surface recent events.

<CardGroup cols={1}>
  <Card title="Lead & Company Enrichment" icon="address-book" href="/use-cases/lead-enrichment">
    Full walkthrough with examples: input format, CLI usage, MCP tool, and API-only approach.
  </Card>
</CardGroup>

## Tips

<Note>
  The `since` parameter is required on batch and polling endpoints. Always pass it to avoid fetching stale data.
</Note>

* Use `compact=true` on batch calls to reduce payload size.
* Poll every 15-60 minutes depending on how time-sensitive your BD pipeline is.
* Use the signal score from `/v1/signal/top` to prioritize outreach — higher scores indicate more significant events.
* Combine partnership radar with signal spikes to identify the highest-conviction opportunities.
