Metadata-Version: 2.4
Name: signallabs
Version: 1.1.0
Summary: Official Python SDK for the Signal Labs competitive intelligence API
Author-email: Signal Labs <support@usesignallabs.com>
License: MIT
Project-URL: Homepage, https://usesignallabs.com
Project-URL: Documentation, https://usesignallabs.com/docs
Project-URL: Repository, https://github.com/emresemercioglu/Signal-labs-cix-platform
Keywords: signal-labs,competitive-intelligence,battlecards,competitor-tracking,api-sdk
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28.0

# signallabs

Official Python SDK for the [Signal Labs](https://usesignallabs.com) competitive intelligence API. Track competitors, generate AI battlecards grounded in researched competitor pages, and read market signals.

## Install

```bash
pip install signallabs
```

Requires Python 3.8 or newer.

## Quickstart

```python
from signallabs import SignalLabs

sl = SignalLabs("sl_live_your_key_here")

# Track a company. Passing a domain kicks off website analysis in the
# background, which fills in offerings and value propositions.
company = sl.companies.create(domain="acme.com")

# Add a competitor. Their site is researched into a full competitor page.
competitors = sl.companies.competitors(company["id"])
added = competitors.add(name="Globex", website="https://globex.com")

# Generate a battlecard once that research has finished.
card = sl.companies.battlecards(company["id"]).generate(
    competitor_id=added[0]["id"],
    enablement_focus="gtm_sales",
)

print(card["overview"])
```

Get an API key from [Settings → API Keys](https://app.usesignallabs.com/settings?tab=api-keys).

To point at a different host:

```python
sl = SignalLabs("sl_live_...", base_url="https://app.usesignallabs.com/api/v1")
```

## Asynchronous operations

Creating a company and adding a competitor both return immediately and continue
working in the background, because website research takes 30-90 seconds. Poll for
the result rather than assuming it is ready:

```python
import time

company = sl.companies.create(domain="acme.com")

profile = sl.companies.profile(company["id"])
while profile["profile_status"] == "pending":
    time.sleep(5)
    profile = sl.companies.profile(company["id"])

print(profile["offerings"], profile["value_propositions"])
```

The same applies to competitors — `competitors.page(id)` reports a
`generation_status` that reads `ready` when the research is complete. Generating a
battlecard before then still works, but the card is less grounded.

## API

### Companies

```python
sl.companies.list()
sl.companies.create(name=None, domain=None, description=..., industry=...)
sl.companies.get(company_id)
sl.companies.profile(company_id)                    # offerings + value propositions
sl.companies.refresh_profile(company_id, force=False)  # re-extract from the website
```

### Products

```python
products = sl.companies.products(company_id)
products.list()
products.create(name, description=..., category=..., target_market=...)
```

### Competitors

```python
competitors = sl.companies.competitors(company_id)
competitors.list(product_id=None)
competitors.add(name, website, relationship_type="direct")
competitors.page(competitor_id)   # researched analysis
competitors.discover(mode="company", offering_id=None, exclude=None)
```

`discover()` returns suggestions only — nothing is created and no allowance is
consumed, so follow up with `add()` for the ones worth tracking.

### Battlecards

```python
battlecards = sl.companies.battlecards(company_id)
battlecards.list(competitor_id=None, enablement_focus=None, version=None)
battlecards.generate(competitor_id, enablement_focus="gtm_sales",
                     special_instructions=None, document_ids=None)
battlecards.generate_landscape(competitor_ids, special_instructions=None,
                              document_ids=None)
```

`enablement_focus` selects the audience the card is written for: `gtm_sales`
(default), `product`, `marketing_growth`, `leadership`, or `custom`. Using
`custom` requires `special_instructions`. Each generation costs 1 credit.

`generate_landscape()` compares 2-8 competitors in a single report.

### Signals

```python
signals = sl.companies.signals(company_id)
signals.list(competitor_id=None, limit=50)
signals.summary(days=7)
```

### AI chat

```python
answer = sl.ai.chat(
    message="How does Globex price against us?",
    company_id=company["id"],
    conversation_id=None,   # continue an existing thread
    competitor_id=None,     # narrow retrieval to one competitor
    mode="hybrid",          # or "internal" for your uploaded documents only
)

print(answer["response"], answer["sources_used"])
```

Answers are grounded in your researched competitor pages, battlecards, signals,
scraped competitor sources and uploaded documents.

## Errors

Failed requests raise `SignalLabsError` carrying the API's structured detail:

```python
from signallabs import SignalLabsError

try:
    sl.companies.battlecards(company_id).generate(competitor_id=competitor_id)
except SignalLabsError as err:
    print(err.code)         # e.g. "insufficient_credits"
    print(err.type)         # e.g. "credit_error"
    print(err.upgrade_url)  # present on credit and limit errors
    print(err.docs_url)     # present on prerequisite errors
```

## Documents

Document upload is not yet exposed here. Upload via the dashboard or
`POST /v1/documents/upload`, then pass the returned ids as `document_ids` when
generating a battlecard to ground it in your own material.

## Links

- [API documentation](https://usesignallabs.com/docs)
- [MCP server](https://usesignallabs.com/docs/mcp) for Claude, Cursor and other AI tools
- [JavaScript SDK](https://www.npmjs.com/package/@signal-labs/sdk)

## License

MIT
