Skip to main content

Python SDK for Canonical company search — find companies using natural language

Project description

canonical-search

Typed Python SDK for Canonical company search — find and enrich companies using natural language or structured filters. A thin, sync + async client over the public REST API.

Install

pip install canonical-search

Requires Python 3.11+.

Quick Start

from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

# Natural-language search
results = client.search("AI healthcare startups")
for company in results.results:
    print(f"{company.name}{company.domain}")

# Async twin
results = await client.asearch("B2B fashion tech companies")

Environment-based config

export CANONICAL_API_KEY=sk_your_key
export CANONICAL_API_BASE_URL=https://trycanonical.ai  # optional
export CANONICAL_TIMEOUT=30.0                          # optional
from canonical_search.config import client_from_env

client = client_from_env()
results = client.search("fintech companies in Europe")

Methods

Every method has an async twin (a-prefixed, e.g. asearch, alookup_companies).

Method Purpose Credits
search(query, top_k=25) Natural-language search 1 per strong result
search_structured(description=None, *, filters=None, intent=None, top_k=25, include_partials=False) Search by typed filters 1 per strong result
find_similar_companies(company_domain, top_k=25, intent=None) Look-alikes for a seed domain 1 per strong result
lookup_companies(names, k=5, disambiguation_mode="auto_when_confident") Resolve names → candidate domains 1 per call when ≥1 candidate
get_company_details(company_domain) Full profile + people + relationships 1 when found (404 free)
get_account_status() Credit balance, plan, rate limits free

top_k is 1–1000. Partial matches (verdict == "partial") are never billed. domain is the public handle — internal numeric ids are never exposed.

Structured search

from canonical_search import CanonicalClient, StructuredFilters, StructuredLocation

client = CanonicalClient(api_key="sk_your_key")

results = client.search_structured(
    description="AI diagnostic platforms for hospitals",  # optional semantic core
    filters=StructuredFilters(
        location=StructuredLocation(countries=["United States"]),
        employee_count_min=50,
        funding_series=["series_a", "series_b"],
        founding_year_min=2018,
    ),
    intent="sales_prospecting",
    top_k=25,
)

funding_series: pre_seed, seed, series_aseries_g_plus, growth, late, bridge, venture, angel, other. intent: sales_prospecting, sales_timing, sales_expansion, competitive_tracking, emerging_competitor_scan, talent_source, recruiter_employer_vet, jobseeker_stability, jobseeker_growth. founder_prior_categories: faang, big_tech, unicorn, top_startup, mbb.

Company details, lookup, account status

details = client.get_company_details("stripe.com")
print(details.company.name, details.company.employee_count)
for person in details.people:
    print(person.name, "—", person.role)

resp = client.lookup_companies(["stripe", "adyen"])
for name, result in resp.results.items():
    if result.auto_resolve_recommended:
        print(name, "→", result.primary_candidate_domain)

status = client.get_account_status()
print(status.plan, status.credits.total, "credits left")

Error handling

from canonical_search import (
    CanonicalClient,
    AuthenticationError,
    InsufficientCreditsError,
    NotFoundError,
    InvalidRequestError,
    RateLimitError,
    APIError,
)

client = CanonicalClient(api_key="sk_your_key")
try:
    results = client.search("fintech")
except InsufficientCreditsError:
    print("Out of credits — top up at /billing")
except RateLimitError as e:
    print(f"Rate limited — retry after {e.retry_after}s")

All exceptions subclass CanonicalError and carry .status_code and .detail: AuthenticationError (401), InsufficientCreditsError (402), NotFoundError (404), InvalidRequestError (400/422), RateLimitError (429, with .retry_after), APIError (5xx).

Response schema

SearchResponse:
    results: list[Company]
    count: int
    query: str
    credits_used: int
    credits_remaining: int | None

Company:
    name: str
    website: str
    domain: str                    # public handle
    description: str
    headquarters: str | None
    employee_count: int | None
    founding_year: int | None
    dimensions: dict | None
    funding: FundingSummary | None
    verdict: str | None
    verdict_reason: str | None

Framework integration

The SDK returns Pydantic models (.model_dump_json() / .model_dump()), so it drops into any framework that accepts Python functions.

LangChain

from langchain_core.tools import tool
from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

@tool
def search_companies(query: str, top_k: int = 25) -> str:
    """Search for companies using natural language."""
    return client.search(query, top_k).model_dump_json()

AutoGen (classic / AG2)

# pip install "ag2[openai]"  — register_function is the v0.2/AG2 API
from autogen import register_function
from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

def search_companies(query: str, top_k: int = 25) -> str:
    """Search for companies using natural language."""
    return client.search(query, top_k).model_dump_json()

register_function(search_companies, caller=assistant, executor=executor,
                  description="Search for companies using natural language")

CrewAI

from crewai.tools import tool
from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

@tool("Company Search")
def search_companies(query: str, top_k: int = 25) -> str:
    """Search for companies using natural language."""
    return client.search(query, top_k).model_dump_json()

Agno

from agno.tools import tool
from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

@tool
def search_companies(query: str, top_k: int = 25) -> str:
    """Search for companies using natural language."""
    return client.search(query, top_k).model_dump_json()

MCP server

Canonical also offers a hosted, OAuth-authenticated remote MCP server at https://trycanonical.ai/mcp/ (add it as a connector in Claude, Cursor, VS Code, etc.). It is a separate hosted service — it is not part of this pip package, and there is no [mcp] extra. See the MCP docs for connection details.

Get an API key

  1. Sign up at trycanonical.ai
  2. Go to Settings → API Keys
  3. Create a new key (starts with sk_)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

canonical_search-0.2.0.tar.gz (10.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

canonical_search-0.2.0-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file canonical_search-0.2.0.tar.gz.

File metadata

  • Download URL: canonical_search-0.2.0.tar.gz
  • Upload date:
  • Size: 10.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.13.3 Darwin/23.6.0

File hashes

Hashes for canonical_search-0.2.0.tar.gz
Algorithm Hash digest
SHA256 b976f3fa04425011d6250124c70cfaa415f283fc4879e1b792c7e913a3f020b6
MD5 c36e53f0c9aef13ef02cbde8c9c7f148
BLAKE2b-256 78d82471c1f8413a6928efe760321b47cb0e590e4daada96ed79634e5c86e89f

See more details on using hashes here.

File details

Details for the file canonical_search-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: canonical_search-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.13.3 Darwin/23.6.0

File hashes

Hashes for canonical_search-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3c28fa66ad9cb1d5b786c0365c02ab9ee42827d8ca65591fd0e02b853b7f56df
MD5 0c5e6864daaa6e75321f21e75d7f9732
BLAKE2b-256 6076764b12593fb8cd153740e634ff0031ba74d3bd69d8f998a53dfc4ba5451b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page