diff --git a/.fern/metadata.json b/.fern/metadata.json index aba6e88..6475d4b 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -1,5 +1,5 @@ { - "cliVersion": "4.0.1", + "cliVersion": "4.2.2", "generatorName": "fernapi/fern-python-sdk", "generatorVersion": "4.59.4", "generatorConfig": { diff --git a/README.md b/README.md index 51bbf66..be179fe 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ The Runcaptain Python library provides convenient access to the Runcaptain APIs - [Usage](#usage) - [Async Client](#async-client) - [Exception Handling](#exception-handling) +- [Streaming](#streaming) - [Advanced](#advanced) - [Access Raw Response Data](#access-raw-response-data) - [Retries](#retries) @@ -40,14 +41,12 @@ client = Captain( organization_id="YOUR_ORGANIZATION_ID", key="YOUR_KEY", ) -client.query.collection_v2( - collection_name="my_documents", - query="What are the key terms in the contract?", - inference=True, - stream=True, - rerank=True, - top_k=10, +response = client.query.collection_v2stream( + collection_name="collection_name", + query="query", ) +for chunk in response.data: + yield chunk ``` ## Async Client @@ -66,14 +65,12 @@ client = AsyncCaptain( async def main() -> None: - await client.query.collection_v2( - collection_name="my_documents", - query="What are the key terms in the contract?", - inference=True, - stream=True, - rerank=True, - top_k=10, + response = await client.query.collection_v2stream( + collection_name="collection_name", + query="query", ) + async for chunk in response.data: + yield chunk asyncio.run(main()) @@ -88,12 +85,31 @@ will be thrown. from runcaptain.core.api_error import ApiError try: - client.query.collection_v2(...) + client.query.collection_v2stream(...) except ApiError as e: print(e.status_code) print(e.body) ``` +## Streaming + +The SDK supports streaming responses, as well, the response will be a generator that you can loop over. + +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +response = client.query.collection_v2stream( + collection_name="collection_name", + query="query", +) +for chunk in response.data: + yield chunk +``` + ## Advanced ### Access Raw Response Data @@ -107,10 +123,12 @@ from runcaptain import Captain client = Captain( ..., ) -response = client.query.with_raw_response.collection_v2(...) -print(response.headers) # access the response headers -print(response.status_code) # access the response status code -print(response.data) # access the underlying object +with client.query.with_raw_response.collection_v2stream(...) as response: + print( + response.headers + ) # access the response headersprint(response.status_code) # access the response status code + for chunk in response.data: + print(chunk) # access the underlying object(s) ``` ### Retries @@ -128,7 +146,7 @@ A request is deemed retryable when any of the following HTTP status codes is ret Use the `max_retries` request option to configure this behavior. ```python -client.query.collection_v2(..., request_options={ +client.query.collection_v2stream(..., request_options={ "max_retries": 1 }) ``` @@ -148,7 +166,7 @@ client = Captain( # Override timeout for a specific method -client.query.collection_v2(..., request_options={ +client.query.collection_v2stream(..., request_options={ "timeout_in_seconds": 1 }) ``` diff --git a/reference.md b/reference.md index 0213529..37001f3 100644 --- a/reference.md +++ b/reference.md @@ -228,7 +228,7 @@ client.collections.delete_collection_v2( Move a collection from one environment to another (e.g., development to production) without reindexing. -All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. +All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. ## Use Cases - Promote a development collection to production after testing @@ -537,7 +537,7 @@ client.collections.delete_document_v2( ## Query -
client.query.collection_v2(...) -> AsyncHttpResponse[QueryResponseV2] +
client.query.collection_v2stream(...) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[QueryStreamEvent]]]
@@ -586,7 +586,7 @@ data: {"type":"stream_complete","metadata":{"totalResults":12,"totalSearches":1} ### Notes - The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. -- Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. +- Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. - Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses.
@@ -608,14 +608,12 @@ client = Captain( organization_id="YOUR_ORGANIZATION_ID", key="YOUR_KEY", ) -client.query.collection_v2( - collection_name="my_documents", - query="What are the key terms in the contract?", - inference=True, - stream=True, - rerank=True, - top_k=10, +response = client.query.collection_v2stream( + collection_name="collection_name", + query="query", ) +for chunk in response.data: + yield chunk ``` @@ -655,7 +653,160 @@ client.query.collection_v2(
-**stream:** `typing.Optional[bool]` — Enable real-time streaming of the response +**top_k:** `typing.Optional[int]` — Number of results to return. Only valid when inference=false. Not supported when inference=true (the agent controls its own search strategy). + +
+
+ +
+
+ +**rerank:** `typing.Optional[bool]` — Enable Voyage AI rerank-2.5 reranking for improved relevance ordering. Adds ~100-300ms latency. + +
+
+ +
+
+ +**metadata_filter:** `typing.Optional[typing.Dict[str, typing.Any]]` — Filter expression for vector search. Supports: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $and, $or + +
+
+ +
+
+ +**custom_prompt:** `typing.Optional[str]` — Custom system prompt to override the default RAG prompt when inference=true. Allows customizing how the LLM processes and responds to the query with the retrieved context. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+ + + + + + +
+ +
client.query.collection_v2(...) -> AsyncHttpResponse[QueryResponseV2] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Execute a natural language query against a collection. + +When `inference=true`, returns an AI-generated response with relevant documents. +When `inference=false`, returns raw search results with content and metadata. + +## Streaming (SSE) + +When `stream: true` and `inference: true`, the response is a Server-Sent Events stream. Every `data:` field is a JSON object with a `type` discriminator. + +### SSE Event Types + +| `type` value | Schema | Description | +|---|---|---| +| `text.delta` | `QueryStreamTextEvent` | Incremental text chunk of the AI response. | +| `tool.start` | `QueryStreamToolStartEvent` | The agent is performing a knowledge-base search. | +| `tool.end` | `QueryStreamToolEndEvent` | A tool call completed. `tool_call_id` correlates with the preceding `tool.start`. | +| `stream_complete` | `QueryStreamCompleteEvent` | Stream finished successfully. Close the connection. | +| `stream_error` | `QueryStreamErrorEvent` | An error occurred. Close the connection. | + +### Example SSE Stream + +``` +data: {"type":"tool.start","seq":1,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","args":{"query":"revenue projections Q4"}} + +data: {"type":"tool.end","seq":2,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","ok":true,"result_summary":{"resultCount":12}} + +data: {"type":"text.delta","seq":3,"run_id":"run_abc","data":"Based on the documents"} +data: {"type":"text.delta","seq":4,"run_id":"run_abc","data":" provided, the revenue"} +data: {"type":"text.delta","seq":5,"run_id":"run_abc","data":" projections for Q4 show"} +data: {"type":"text.delta","seq":6,"run_id":"run_abc","data":" a 15% increase over Q3."} + +data: {"type":"stream_complete","metadata":{"totalResults":12,"totalSearches":1},"stats":{"totalTokens":150}} +``` + +### Notes + +- The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. +- Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. +- Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.query.collection_v2( + collection_name="my_documents", + query="What are the key terms in the contract?", + inference=True, + rerank=True, + top_k=10, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_name:** `str` + +
+
+ +
+
+ +**query:** `str` — The natural language query to search for + +
+
+ +
+
+ +**inference:** `typing.Optional[bool]` — Enable LLM-generated answers based on the relevant sections retrieved. When false, returns raw search results.
@@ -1906,7 +2057,7 @@ client.indexing.index_azure_directory_v2(
-Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}. +Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}.
@@ -2355,8 +2506,8 @@ client.indexing.index_r2directory_v2( Index documents from public URLs into a collection. No cloud storage credentials required. You can provide either: -- `url` — a single URL string for one document -- `urls` — an array of URL strings for multiple documents +- `url` — a single URL string for one document +- `urls` — an array of URL strings for multiple documents Supported file types: PDF, DOCX, DOC, XLSX, XLS, CSV, TSV, TXT, MD, JSON, YAML, YML, PNG, JPG, JPEG, GIF, BMP, TIFF. Documents are downloaded and processed through the same pipeline as cloud storage indexing. @@ -2670,6 +2821,7 @@ client = Captain( ) client.datasets.search_dataset( dataset="dataset_name", + q="climate change policy", ) ``` @@ -2694,6 +2846,22 @@ client.datasets.search_dataset(
+**q:** `str` — Search query + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum number of results to return (default: 10, max: 100) + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -2794,3 +2962,6440 @@ client.datasets.get_dataset_article(
+## General +
client.general.search(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search across all entity types (companies, people, investors, funds, deals, etc.) in a unified query. Returns matching entities with their type and basic information. Use this for broad discovery before drilling into specific entity types. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.general.search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum results + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.general.search_shared() -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for entities shared across your organization. Returns entities that multiple team members have accessed or tagged. Useful for discovering commonly referenced companies, investors, or people within your team. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.general.search_shared() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.general.entity_people(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get people associated with any entity (company employees, fund team members, investor partners, etc.). Returns names, titles, and LinkedIn profiles for key people. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.general.entity_people( + entity_id="openai", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**entity_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.general.entity_locations(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get office locations for any entity. Returns headquarters and branch office addresses with city, state, country, and full address details. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.general.entity_locations( + entity_id="openai", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**entity_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.general.entity_affiliates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get affiliated entities and subsidiaries for any entity. Returns parent companies, subsidiaries, and related entities with ownership information. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.general.entity_affiliates( + entity_id="openai", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**entity_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.general.entity_news(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get recent news articles and mentions for any entity. Returns article titles, URLs, sources, publication dates, and snippets. Useful for tracking announcements, funding news, and company updates. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.general.entity_news( + entity_id="openai", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**entity_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.general.entity_updates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get changelog of data updates for any entity. Returns history of changes to the entity's profile, tracking when information was added or modified. Useful for monitoring data freshness. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.general.entity_updates( + entity_id="openai", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**entity_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Companies +
client.companies.search() -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for companies by name, industry, or location. Returns matching company profiles with employee count, industry classification, founding date, and headquarters. Use this to find company entity IDs for detailed lookups. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.bio(...) -> AsyncHttpResponse[typing.Any] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get comprehensive company profile including description, founding date, headquarters location, employee count, industry classification, and social media profiles. This is the primary endpoint for company overview data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.bio( + company_id="019cb8ac-adee-749e-a75e-a1c236f20f72", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.industries(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get industry classifications including NAICS codes, SIC codes, and industry descriptions. Useful for filtering companies by vertical or sector. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.industries( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.financials(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get financial statements for public companies including revenue, net income, assets, and liabilities. Returns most recent fiscal year data or specific year if requested. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.financials( + company_id="ody_co_sample_msft", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.financials_recent(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get most recent financial statements for public companies. Convenience endpoint that automatically returns the latest available fiscal year data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.financials_recent( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.financing_recent(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get most recent funding rounds including round type, amount raised, investors, and valuation. Returns detailed information about the latest equity financing event. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.financing_recent( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.active_investors(...) -> AsyncHttpResponse[typing.Any] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get current investors in the company from recent funding rounds. Returns investor names, types, and contact information. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.active_investors( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.all_investors(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get complete investor history including historical investors from all funding rounds. Returns comprehensive list of all investors who have participated in company financing. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.all_investors( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.deals(...) -> AsyncHttpResponse[typing.Any] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get all deals for a company including funding rounds and acquisitions. Each deal includes the deal type, round name, investors involved, amount raised, and status. Funding rounds are sourced from investor data, while acquisitions are sourced from M&A records. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.deals( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.service_providers(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get service providers working with the company including legal counsel, accounting firms, and consultants. Returns firm names, service types, and engagement information. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.service_providers( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.service_providers_deal(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get service providers involved in specific financing deals including investment bankers, legal advisors, and financial consultants. Returns provider details specific to fundraising transactions. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.service_providers_deal( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.debt_financing_recent(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get most recent debt financing rounds including venture debt, credit lines, and loans. Returns lender information, amounts, and terms. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.debt_financing_recent( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.similar(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get companies similar to this one based on industry, size, and business model. Returns competitor and peer company information with similarity scores. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.similar( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.social_analytics(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get social media metrics including LinkedIn followers, Twitter engagement, and Facebook presence. Useful for measuring company online visibility and growth. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.social_analytics( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.vc_exit_predictions(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Coming Soon: Get predicted likelihood and timeline for company exit events (IPO or acquisition). Will return ML-based exit probability scores and estimated exit valuation ranges when implemented. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.vc_exit_predictions( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.companies.updates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get changelog of updates to company profile data. Returns history of changes to company information with timestamps and modified fields. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.companies.updates( + company_id="openai.com", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**company_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## People +
client.people.search(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for professionals by name, company, title, or location. Returns matching profiles with current position, company, and LinkedIn URL. Use this to find person entity IDs for detailed lookups. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.people.search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**title:** `typing.Optional[str]` — Filter by job title + +
+
+ +
+
+ +**location:** `typing.Optional[str]` — Filter by location + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum results + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.people.bio(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get comprehensive person profile including headline, summary, current company, location, and social profiles. This is the primary endpoint for person overview data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.people.bio( + person_id="ody_pe_019cb8ac-f123-749e-a75e-e5f669g53c05", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**person_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.people.contact(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get contact information including email addresses, phone numbers, and social media profiles. Returns verified contact details for outreach. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.people.contact( + person_id="linkedin.com/in/samaltman", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**person_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.people.education_work(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get complete professional history including work experience and education. Returns job positions with companies, titles, dates, and degree information with schools and majors. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.people.education_work( + person_id="linkedin.com/in/samaltman", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**person_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.people.updates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get changelog of updates to person profile data. Returns history of career moves, title changes, and profile updates with timestamps. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.people.updates( + person_id="linkedin.com/in/samaltman", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**person_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Deals +
client.deals.search(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for funding rounds and deals by company, deal type, amount range, or date. Returns matching transactions with deal type, amount, date, and participants. Use this to find deal entity IDs for detailed lookups. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**deal_type:** `typing.Optional[str]` — Filter by deal type + +
+
+ +
+
+ +**min_amount:** `typing.Optional[float]` — Minimum deal amount + +
+
+ +
+
+ +**max_amount:** `typing.Optional[float]` — Maximum deal amount + +
+
+ +
+
+ +**start_date:** `typing.Optional[str]` — Start date (YYYY-MM-DD) + +
+
+ +
+
+ +**end_date:** `typing.Optional[str]` — End date (YYYY-MM-DD) + +
+
+ +
+
+ +**page:** `typing.Optional[int]` — Page number + +
+
+ +
+
+ +**page_size:** `typing.Optional[int]` — Results per page + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.bio(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get comprehensive deal information including amount, type, date, company, and investor participants. This is the primary endpoint for deal overview data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.bio( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.detailed(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get comprehensive deal data combining bio, investors, valuation, and terms in a single response. Use this for complete deal intelligence without multiple API calls. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.detailed( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.investors(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get all investors participating in the deal including lead and follow-on investors. Returns investor names, roles, and investment amounts. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.investors( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.service_providers(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get service providers involved in the deal including legal counsel, investment bankers, and financial advisors. Returns firm names and service types. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.service_providers( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.valuation(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get valuation information including pre-money and post-money valuations, equity percentage, and pricing details. Useful for understanding deal economics. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.valuation( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.stock_info(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get current stock price and market data for the company involved in this deal. Only applicable for public companies. Returns real-time stock quotes and market metrics. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.stock_info( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.cap_table(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Coming Soon: Get capitalization table showing ownership breakdown after the deal. Will return equity ownership percentages, share counts, and investor stakes when implemented. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.cap_table( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.tranche(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Coming Soon: Get information about deal tranches and payment schedules for structured financing. Will return tranche amounts, dates, and conditions when implemented. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.tranche( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.debt_lenders(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get lenders participating in debt financing deals. Returns lender names, amounts, and terms for venture debt and credit facilities. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.debt_lenders( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.multiples(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Coming Soon: Get valuation multiples for the deal including revenue multiple, EBITDA multiple, and comparable transaction metrics. Will return detailed valuation analysis when implemented. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.multiples( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deals.updates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get changelog of updates to deal information. Returns history of changes to deal data with timestamps and modified fields. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.deals.updates( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Investors +
client.investors.search(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for venture capital firms, angel investors, and institutional investors by name. Returns matching investor profiles with investment focus, portfolio size, and notable investments. Use this to find investor entity IDs for detailed lookups. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page:** `typing.Optional[int]` — Page number + +
+
+ +
+
+ +**page_size:** `typing.Optional[int]` — Results per page + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.bio(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get comprehensive investor profile including description, investment thesis, stage focus, sector focus, and notable portfolio companies. This is the primary endpoint for investor overview data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.bio( + id="ody_inv_019cb8ac-g789-749e-a75e-h7i880j64d16", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.active_investments(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get current portfolio companies that the investor has active positions in. Returns company names, investment dates, and current status. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.active_investments( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.all_investments(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get complete investment history including current portfolio and exited positions. Returns all companies the investor has backed with investment details and outcomes. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.all_investments( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.preferences(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get investment preferences including stage focus, sector preferences, geography, and typical check size. Useful for determining investment fit. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.preferences( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.funds(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get all funds managed by the investor including fund names, sizes, vintage years, and status. Returns complete fund portfolio for multi-fund investors. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.funds( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.funds_latest(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get information about the investor's most recent fund including size, vintage year, and deployment status. Useful for understanding current investment capacity. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.funds_latest( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.board_seats(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get board seats held by the investor's team members. Returns companies where investor partners serve on the board of directors. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.board_seats( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.service_providers(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get service providers used by the investor including legal counsel, fund administrators, and consultants. Returns firm names and service types. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.service_providers( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.service_providers_deal(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get service providers involved in the investor's deal flow including transaction advisors and due diligence firms. Returns provider details specific to deal execution. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.service_providers_deal( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.investors.updates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get changelog of updates to investor profile data. Returns history of changes including new investments, fund raises, and team changes with timestamps. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.investors.updates( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Funds +
client.funds.search(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for venture capital and private equity funds by name. Returns matching fund profiles with size, vintage year, and investment focus. Use this to find fund entity IDs for detailed lookups. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**vintage_year:** `typing.Optional[int]` — Filter by vintage year + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum results + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.bio(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get comprehensive fund profile including fund size, vintage year, investment strategy, stage focus, and sector focus. This is the primary endpoint for fund overview data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.bio( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.performance(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Coming Soon: Get fund performance metrics including IRR, TVPI, DPI, and RVPI. Will return LP-level performance data when implemented with proprietary fund reporting. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.performance( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.active_investments(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get current portfolio companies invested by this specific fund. Returns company names, investment amounts, and current status. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.active_investments( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.all_investments(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get complete investment history for this specific fund including current and exited positions. Returns all companies backed by the fund with outcomes. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.all_investments( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.commitments(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get limited partner commitments to the fund including LP names and commitment amounts. Returns investor base and capital structure. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.commitments( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.cash_flows(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Coming Soon: Get fund cash flow history including capital calls and distributions. Will return quarterly cash flow statements when implemented with LP reporting data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.cash_flows( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.benchmark(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Coming Soon: Get fund performance compared to industry benchmarks and peer funds. Will return quartile rankings and comparative metrics when implemented. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.benchmark( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.people(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get investment team members for the fund including partners, principals, and associates. Returns names, titles, and LinkedIn profiles. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.people( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.preferences(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get investment criteria and preferences for the fund including stage focus, sector preferences, geography, and check size ranges. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.preferences( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.funds.updates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get changelog of updates to fund profile data. Returns history of changes including new investments, exits, and team changes with timestamps. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.funds.updates( + fund_id="sequoia", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**fund_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## LimitedPartners +
client.limited_partners.lps_search(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for institutional limited partners including pension funds, endowments, and family offices. Returns matching LP profiles with total commitments and fund relationships. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.limited_partners.lps_search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum results + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.limited_partners.lps_bio(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get comprehensive limited partner profile including institution type, total assets under management, investment strategy, and notable fund commitments. This is the primary endpoint for LP overview data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.limited_partners.lps_bio( + lp_id="calpers", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**lp_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.limited_partners.lps_commitments_detailed(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get detailed fund commitments including specific fund names, commitment amounts, vintage years, and commitment status. Returns complete LP portfolio. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.limited_partners.lps_commitments_detailed( + lp_id="calpers", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**lp_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.limited_partners.lps_commitments_aggregates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get aggregated commitment statistics including total commitments by vintage year, fund type, and geography. Returns high-level allocation summary. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.limited_partners.lps_commitments_aggregates( + lp_id="calpers", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**lp_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.limited_partners.lps_allocations_target(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get target allocation percentages by asset class, geography, and strategy. Returns investment policy guidelines and target portfolio mix. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.limited_partners.lps_allocations_target( + lp_id="calpers", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**lp_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.limited_partners.lps_allocations_actual(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get actual current allocation percentages by asset class, geography, and strategy. Returns real portfolio composition and compare to targets. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.limited_partners.lps_allocations_actual( + lp_id="calpers", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**lp_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.limited_partners.lps_commitment_preferences(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get commitment preferences including preferred fund sizes, vintage year focus, and investment stage preferences. Useful for GP fundraising targeting. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.limited_partners.lps_commitment_preferences( + lp_id="calpers", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**lp_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.limited_partners.lps_service_providers(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get service providers used by the LP including consultants, custodians, and legal advisors. Returns firm names and service types. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.limited_partners.lps_service_providers( + lp_id="calpers", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**lp_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.limited_partners.lps_updates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get changelog of updates to LP profile data. Returns history of changes including new commitments, policy changes, and team updates with timestamps. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.limited_partners.lps_updates( + lp_id="calpers", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**lp_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## ServiceProviders +
client.service_providers.search(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for service providers including law firms, accounting firms, investment banks, and consultants. Returns matching provider profiles with specializations and notable clients. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.service_providers.search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum results + +
+
+ +
+
+ +**provider_type:** `typing.Optional[str]` — Provider type filter + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.service_providers.bio(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get comprehensive service provider profile including firm description, practice areas, office locations, and notable work. This is the primary endpoint for provider overview data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.service_providers.bio( + provider_id="wilson-sonsini", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**provider_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.service_providers.companies(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get companies that have engaged this service provider. Returns client list with engagement types and sectors served. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.service_providers.companies( + provider_id="wilson-sonsini", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**provider_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.service_providers.deals(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get deals where this provider was involved as advisor, counsel, or banker. Returns transaction history with roles and deal values. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.service_providers.deals( + provider_id="wilson-sonsini", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**provider_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.service_providers.investors(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get investors that have engaged this service provider. Returns investor clients with engagement types and fund formation work. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.service_providers.investors( + provider_id="wilson-sonsini", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**provider_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.service_providers.funds(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get funds that have engaged this service provider. Returns fund formation and compliance work with engagement details. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.service_providers.funds( + provider_id="wilson-sonsini", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**provider_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.service_providers.limited_partners(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get limited partners that have engaged this service provider. Returns LP clients with service types and relationship details. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.service_providers.limited_partners( + provider_id="wilson-sonsini", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**provider_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.service_providers.updates(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get changelog of updates to service provider profile data. Returns history of changes including new engagements, office openings, and team changes with timestamps. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.service_providers.updates( + provider_id="wilson-sonsini", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**provider_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Patents +
client.patents.search(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for patents by title, inventor, assignee, or classification. Returns matching patents with patent numbers, titles, filing dates, and status. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.patents.search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum results + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.patents.get_by_id(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get detailed patent information including abstract, claims, inventors, citations, and prosecution history. Returns comprehensive patent profile. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.patents.get_by_id( + id="deal_openai_0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.patents.get_file(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Download patent file wrapper or PDF document. Returns patent documentation and prosecution history files. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.patents.get_file( + entity_id="US11234567B2", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**entity_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## CreditAnalysis +
client.credit_analysis.news_search(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Search for credit-related news and filings including bond issuances, credit rating changes, and default events. Returns matching news with dates, sources, and content. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.credit_analysis.news_search() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**start_date:** `typing.Optional[str]` — Start date (YYYY-MM-DD) + +
+
+ +
+
+ +**end_date:** `typing.Optional[str]` — End date (YYYY-MM-DD) + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum results + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.credit_analysis.news_recent() -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get most recent credit news and filings. Returns latest credit events, ratings, and bond issuances from the past 30 days. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.credit_analysis.news_recent() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.credit_analysis.news_detail(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get detailed credit news article or filing including full text, metadata, and related entities. Returns comprehensive news item with analysis. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.credit_analysis.news_detail( + news_id="abc123def456", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**news_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.credit_analysis.news_attachment(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Download attachment files associated with credit news including prospectuses, indentures, and rating reports. Returns document files. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.credit_analysis.news_attachment( + news_id="abc123def456", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**news_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.credit_analysis.news_bulk(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve multiple credit news articles by ID in a single request. Returns batch results with article details for each requested ID. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.credit_analysis.news_bulk( + queries=["Apple credit rating", "Tesla debt analysis"], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**queries:** `typing.Optional[typing.Sequence[str]]` — List of search queries + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Fundamentals +
client.fundamentals.sandbox() -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get sample entities for testing and development. Returns mock company, person, investor, and fund data for sandbox environment testing. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.fundamentals.sandbox() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.fundamentals.lookup_tables() -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get available reference lookup tables including industry codes, country codes, and entity type classifications. Returns list of available tables with descriptions. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.fundamentals.lookup_tables() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.fundamentals.lookup_table_values(...) -> AsyncHttpResponse[typing.Dict[str, typing.Any]] +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get values from a specific lookup table. Returns table data with codes, descriptions, and hierarchical relationships for reference data. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from runcaptain import Captain + +client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", +) +client.fundamentals.lookup_table_values( + table_id="sectors", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**table_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ diff --git a/src/runcaptain/__init__.py b/src/runcaptain/__init__.py index c0b7499..befd5c2 100644 --- a/src/runcaptain/__init__.py +++ b/src/runcaptain/__init__.py @@ -32,9 +32,9 @@ JobProgress, JobProgressCurrentStage, JobResult, + JobStatus, JobStatusResponseV2, JobStatusResponseV2JobType, - JobStatusResponseV2Status, QueryResponseV2, QueryStreamCompleteEvent, QueryStreamErrorEvent, @@ -59,10 +59,28 @@ ConflictError, ForbiddenError, NotFoundError, + NotImplementedError, ServiceUnavailableError, UnauthorizedError, ) - from . import collections, datasets, indexing, jobs, query + from . import ( + collections, + companies, + credit_analysis, + datasets, + deals, + fundamentals, + funds, + general, + indexing, + investors, + jobs, + limited_partners, + patents, + people, + query, + service_providers, + ) from .client import AsyncCaptain, Captain from .collections import ChangeEnvironmentRequestV2NewEnvironment from .environment import CaptainEnvironment @@ -134,10 +152,11 @@ "JobProgress": ".types", "JobProgressCurrentStage": ".types", "JobResult": ".types", + "JobStatus": ".types", "JobStatusResponseV2": ".types", "JobStatusResponseV2JobType": ".types", - "JobStatusResponseV2Status": ".types", "NotFoundError": ".errors", + "NotImplementedError": ".errors", "QueryResponseV2": ".types", "QueryStreamCompleteEvent": ".types", "QueryStreamErrorEvent": ".types", @@ -160,10 +179,21 @@ "ValidationErrorLocItem": ".types", "__version__": ".version", "collections": ".collections", + "companies": ".companies", + "credit_analysis": ".credit_analysis", "datasets": ".datasets", + "deals": ".deals", + "fundamentals": ".fundamentals", + "funds": ".funds", + "general": ".general", "indexing": ".indexing", + "investors": ".investors", "jobs": ".jobs", + "limited_partners": ".limited_partners", + "patents": ".patents", + "people": ".people", "query": ".query", + "service_providers": ".service_providers", } @@ -237,10 +267,11 @@ def __dir__(): "JobProgress", "JobProgressCurrentStage", "JobResult", + "JobStatus", "JobStatusResponseV2", "JobStatusResponseV2JobType", - "JobStatusResponseV2Status", "NotFoundError", + "NotImplementedError", "QueryResponseV2", "QueryStreamCompleteEvent", "QueryStreamErrorEvent", @@ -263,8 +294,19 @@ def __dir__(): "ValidationErrorLocItem", "__version__", "collections", + "companies", + "credit_analysis", "datasets", + "deals", + "fundamentals", + "funds", + "general", "indexing", + "investors", "jobs", + "limited_partners", + "patents", + "people", "query", + "service_providers", ] diff --git a/src/runcaptain/client.py b/src/runcaptain/client.py index e37282b..663ca3b 100644 --- a/src/runcaptain/client.py +++ b/src/runcaptain/client.py @@ -13,10 +13,21 @@ if typing.TYPE_CHECKING: from .collections.client import AsyncCollectionsClient, CollectionsClient + from .companies.client import AsyncCompaniesClient, CompaniesClient + from .credit_analysis.client import AsyncCreditAnalysisClient, CreditAnalysisClient from .datasets.client import AsyncDatasetsClient, DatasetsClient + from .deals.client import AsyncDealsClient, DealsClient + from .fundamentals.client import AsyncFundamentalsClient, FundamentalsClient + from .funds.client import AsyncFundsClient, FundsClient + from .general.client import AsyncGeneralClient, GeneralClient from .indexing.client import AsyncIndexingClient, IndexingClient + from .investors.client import AsyncInvestorsClient, InvestorsClient from .jobs.client import AsyncJobsClient, JobsClient + from .limited_partners.client import AsyncLimitedPartnersClient, LimitedPartnersClient + from .patents.client import AsyncPatentsClient, PatentsClient + from .people.client import AsyncPeopleClient, PeopleClient from .query.client import AsyncQueryClient, QueryClient + from .service_providers.client import AsyncServiceProvidersClient, ServiceProvidersClient class Captain: @@ -100,6 +111,17 @@ def __init__( self._indexing: typing.Optional[IndexingClient] = None self._jobs: typing.Optional[JobsClient] = None self._datasets: typing.Optional[DatasetsClient] = None + self._general: typing.Optional[GeneralClient] = None + self._companies: typing.Optional[CompaniesClient] = None + self._people: typing.Optional[PeopleClient] = None + self._deals: typing.Optional[DealsClient] = None + self._investors: typing.Optional[InvestorsClient] = None + self._funds: typing.Optional[FundsClient] = None + self._limited_partners: typing.Optional[LimitedPartnersClient] = None + self._service_providers: typing.Optional[ServiceProvidersClient] = None + self._patents: typing.Optional[PatentsClient] = None + self._credit_analysis: typing.Optional[CreditAnalysisClient] = None + self._fundamentals: typing.Optional[FundamentalsClient] = None @property def collections(self): @@ -141,6 +163,94 @@ def datasets(self): self._datasets = DatasetsClient(client_wrapper=self._client_wrapper) return self._datasets + @property + def general(self): + if self._general is None: + from .general.client import GeneralClient # noqa: E402 + + self._general = GeneralClient(client_wrapper=self._client_wrapper) + return self._general + + @property + def companies(self): + if self._companies is None: + from .companies.client import CompaniesClient # noqa: E402 + + self._companies = CompaniesClient(client_wrapper=self._client_wrapper) + return self._companies + + @property + def people(self): + if self._people is None: + from .people.client import PeopleClient # noqa: E402 + + self._people = PeopleClient(client_wrapper=self._client_wrapper) + return self._people + + @property + def deals(self): + if self._deals is None: + from .deals.client import DealsClient # noqa: E402 + + self._deals = DealsClient(client_wrapper=self._client_wrapper) + return self._deals + + @property + def investors(self): + if self._investors is None: + from .investors.client import InvestorsClient # noqa: E402 + + self._investors = InvestorsClient(client_wrapper=self._client_wrapper) + return self._investors + + @property + def funds(self): + if self._funds is None: + from .funds.client import FundsClient # noqa: E402 + + self._funds = FundsClient(client_wrapper=self._client_wrapper) + return self._funds + + @property + def limited_partners(self): + if self._limited_partners is None: + from .limited_partners.client import LimitedPartnersClient # noqa: E402 + + self._limited_partners = LimitedPartnersClient(client_wrapper=self._client_wrapper) + return self._limited_partners + + @property + def service_providers(self): + if self._service_providers is None: + from .service_providers.client import ServiceProvidersClient # noqa: E402 + + self._service_providers = ServiceProvidersClient(client_wrapper=self._client_wrapper) + return self._service_providers + + @property + def patents(self): + if self._patents is None: + from .patents.client import PatentsClient # noqa: E402 + + self._patents = PatentsClient(client_wrapper=self._client_wrapper) + return self._patents + + @property + def credit_analysis(self): + if self._credit_analysis is None: + from .credit_analysis.client import CreditAnalysisClient # noqa: E402 + + self._credit_analysis = CreditAnalysisClient(client_wrapper=self._client_wrapper) + return self._credit_analysis + + @property + def fundamentals(self): + if self._fundamentals is None: + from .fundamentals.client import FundamentalsClient # noqa: E402 + + self._fundamentals = FundamentalsClient(client_wrapper=self._client_wrapper) + return self._fundamentals + class AsyncCaptain: """ @@ -223,6 +333,17 @@ def __init__( self._indexing: typing.Optional[AsyncIndexingClient] = None self._jobs: typing.Optional[AsyncJobsClient] = None self._datasets: typing.Optional[AsyncDatasetsClient] = None + self._general: typing.Optional[AsyncGeneralClient] = None + self._companies: typing.Optional[AsyncCompaniesClient] = None + self._people: typing.Optional[AsyncPeopleClient] = None + self._deals: typing.Optional[AsyncDealsClient] = None + self._investors: typing.Optional[AsyncInvestorsClient] = None + self._funds: typing.Optional[AsyncFundsClient] = None + self._limited_partners: typing.Optional[AsyncLimitedPartnersClient] = None + self._service_providers: typing.Optional[AsyncServiceProvidersClient] = None + self._patents: typing.Optional[AsyncPatentsClient] = None + self._credit_analysis: typing.Optional[AsyncCreditAnalysisClient] = None + self._fundamentals: typing.Optional[AsyncFundamentalsClient] = None @property def collections(self): @@ -264,6 +385,94 @@ def datasets(self): self._datasets = AsyncDatasetsClient(client_wrapper=self._client_wrapper) return self._datasets + @property + def general(self): + if self._general is None: + from .general.client import AsyncGeneralClient # noqa: E402 + + self._general = AsyncGeneralClient(client_wrapper=self._client_wrapper) + return self._general + + @property + def companies(self): + if self._companies is None: + from .companies.client import AsyncCompaniesClient # noqa: E402 + + self._companies = AsyncCompaniesClient(client_wrapper=self._client_wrapper) + return self._companies + + @property + def people(self): + if self._people is None: + from .people.client import AsyncPeopleClient # noqa: E402 + + self._people = AsyncPeopleClient(client_wrapper=self._client_wrapper) + return self._people + + @property + def deals(self): + if self._deals is None: + from .deals.client import AsyncDealsClient # noqa: E402 + + self._deals = AsyncDealsClient(client_wrapper=self._client_wrapper) + return self._deals + + @property + def investors(self): + if self._investors is None: + from .investors.client import AsyncInvestorsClient # noqa: E402 + + self._investors = AsyncInvestorsClient(client_wrapper=self._client_wrapper) + return self._investors + + @property + def funds(self): + if self._funds is None: + from .funds.client import AsyncFundsClient # noqa: E402 + + self._funds = AsyncFundsClient(client_wrapper=self._client_wrapper) + return self._funds + + @property + def limited_partners(self): + if self._limited_partners is None: + from .limited_partners.client import AsyncLimitedPartnersClient # noqa: E402 + + self._limited_partners = AsyncLimitedPartnersClient(client_wrapper=self._client_wrapper) + return self._limited_partners + + @property + def service_providers(self): + if self._service_providers is None: + from .service_providers.client import AsyncServiceProvidersClient # noqa: E402 + + self._service_providers = AsyncServiceProvidersClient(client_wrapper=self._client_wrapper) + return self._service_providers + + @property + def patents(self): + if self._patents is None: + from .patents.client import AsyncPatentsClient # noqa: E402 + + self._patents = AsyncPatentsClient(client_wrapper=self._client_wrapper) + return self._patents + + @property + def credit_analysis(self): + if self._credit_analysis is None: + from .credit_analysis.client import AsyncCreditAnalysisClient # noqa: E402 + + self._credit_analysis = AsyncCreditAnalysisClient(client_wrapper=self._client_wrapper) + return self._credit_analysis + + @property + def fundamentals(self): + if self._fundamentals is None: + from .fundamentals.client import AsyncFundamentalsClient # noqa: E402 + + self._fundamentals = AsyncFundamentalsClient(client_wrapper=self._client_wrapper) + return self._fundamentals + def _get_base_url(*, base_url: typing.Optional[str] = None, environment: CaptainEnvironment) -> str: if base_url is not None: diff --git a/src/runcaptain/collections/client.py b/src/runcaptain/collections/client.py index 4bda78d..eb76ec8 100644 --- a/src/runcaptain/collections/client.py +++ b/src/runcaptain/collections/client.py @@ -148,7 +148,7 @@ def change_collection_environment_v2( """ Move a collection from one environment to another (e.g., development to production) without reindexing. - All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. + All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. ## Use Cases - Promote a development collection to production after testing @@ -458,7 +458,7 @@ async def change_collection_environment_v2( """ Move a collection from one environment to another (e.g., development to production) without reindexing. - All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. + All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. ## Use Cases - Promote a development collection to production after testing diff --git a/src/runcaptain/collections/raw_client.py b/src/runcaptain/collections/raw_client.py index 15af9fc..fedfa71 100644 --- a/src/runcaptain/collections/raw_client.py +++ b/src/runcaptain/collections/raw_client.py @@ -176,7 +176,7 @@ def change_collection_environment_v2( """ Move a collection from one environment to another (e.g., development to production) without reindexing. - All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. + All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. ## Use Cases - Promote a development collection to production after testing @@ -553,7 +553,7 @@ async def change_collection_environment_v2( """ Move a collection from one environment to another (e.g., development to production) without reindexing. - All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. + All files, indexed data, and vector embeddings are preserved. The collection's internal ID stays the same — only the environment label changes. ## Use Cases - Promote a development collection to production after testing diff --git a/src/runcaptain/companies/__init__.py b/src/runcaptain/companies/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/companies/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/companies/client.py b/src/runcaptain/companies/client.py new file mode 100644 index 0000000..208ea09 --- /dev/null +++ b/src/runcaptain/companies/client.py @@ -0,0 +1,1203 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawCompaniesClient, RawCompaniesClient + + +class CompaniesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawCompaniesClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawCompaniesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawCompaniesClient + """ + return self._raw_client + + def search(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Dict[str, typing.Any]: + """ + Search for companies by name, industry, or location. Returns matching company profiles with employee count, industry classification, founding date, and headquarters. Use this to find company entity IDs for detailed lookups. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.search() + """ + _response = self._raw_client.search(request_options=request_options) + return _response.data + + def bio(self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Any: + """ + Get comprehensive company profile including description, founding date, headquarters location, employee count, industry classification, and social media profiles. This is the primary endpoint for company overview data. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Any + Company bio retrieved successfully + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.bio( + company_id="019cb8ac-adee-749e-a75e-a1c236f20f72", + ) + """ + _response = self._raw_client.bio(company_id, request_options=request_options) + return _response.data + + def industries( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get industry classifications including NAICS codes, SIC codes, and industry descriptions. Useful for filtering companies by vertical or sector. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.industries( + company_id="openai.com", + ) + """ + _response = self._raw_client.industries(company_id, request_options=request_options) + return _response.data + + def financials( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get financial statements for public companies including revenue, net income, assets, and liabilities. Returns most recent fiscal year data or specific year if requested. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.financials( + company_id="ody_co_sample_msft", + ) + """ + _response = self._raw_client.financials(company_id, request_options=request_options) + return _response.data + + def financials_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get most recent financial statements for public companies. Convenience endpoint that automatically returns the latest available fiscal year data. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.financials_recent( + company_id="openai.com", + ) + """ + _response = self._raw_client.financials_recent(company_id, request_options=request_options) + return _response.data + + def financing_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get most recent funding rounds including round type, amount raised, investors, and valuation. Returns detailed information about the latest equity financing event. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.financing_recent( + company_id="openai.com", + ) + """ + _response = self._raw_client.financing_recent(company_id, request_options=request_options) + return _response.data + + def active_investors( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Any: + """ + Get current investors in the company from recent funding rounds. Returns investor names, types, and contact information. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Any + Active investors retrieved successfully + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.active_investors( + company_id="openai.com", + ) + """ + _response = self._raw_client.active_investors(company_id, request_options=request_options) + return _response.data + + def all_investors( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get complete investor history including historical investors from all funding rounds. Returns comprehensive list of all investors who have participated in company financing. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.all_investors( + company_id="openai.com", + ) + """ + _response = self._raw_client.all_investors(company_id, request_options=request_options) + return _response.data + + def deals(self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Any: + """ + Get all deals for a company including funding rounds and acquisitions. Each deal includes the deal type, round name, investors involved, amount raised, and status. Funding rounds are sourced from investor data, while acquisitions are sourced from M&A records. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Any + Company deals retrieved successfully + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.deals( + company_id="openai.com", + ) + """ + _response = self._raw_client.deals(company_id, request_options=request_options) + return _response.data + + def service_providers( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers working with the company including legal counsel, accounting firms, and consultants. Returns firm names, service types, and engagement information. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.service_providers( + company_id="openai.com", + ) + """ + _response = self._raw_client.service_providers(company_id, request_options=request_options) + return _response.data + + def service_providers_deal( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers involved in specific financing deals including investment bankers, legal advisors, and financial consultants. Returns provider details specific to fundraising transactions. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.service_providers_deal( + company_id="openai.com", + ) + """ + _response = self._raw_client.service_providers_deal(company_id, request_options=request_options) + return _response.data + + def debt_financing_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get most recent debt financing rounds including venture debt, credit lines, and loans. Returns lender information, amounts, and terms. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.debt_financing_recent( + company_id="openai.com", + ) + """ + _response = self._raw_client.debt_financing_recent(company_id, request_options=request_options) + return _response.data + + def similar( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get companies similar to this one based on industry, size, and business model. Returns competitor and peer company information with similarity scores. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.similar( + company_id="openai.com", + ) + """ + _response = self._raw_client.similar(company_id, request_options=request_options) + return _response.data + + def social_analytics( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get social media metrics including LinkedIn followers, Twitter engagement, and Facebook presence. Useful for measuring company online visibility and growth. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.social_analytics( + company_id="openai.com", + ) + """ + _response = self._raw_client.social_analytics(company_id, request_options=request_options) + return _response.data + + def vc_exit_predictions( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get predicted likelihood and timeline for company exit events (IPO or acquisition). Will return ML-based exit probability scores and estimated exit valuation ranges when implemented. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.vc_exit_predictions( + company_id="openai.com", + ) + """ + _response = self._raw_client.vc_exit_predictions(company_id, request_options=request_options) + return _response.data + + def updates( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to company profile data. Returns history of changes to company information with timestamps and modified fields. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.companies.updates( + company_id="openai.com", + ) + """ + _response = self._raw_client.updates(company_id, request_options=request_options) + return _response.data + + +class AsyncCompaniesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawCompaniesClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawCompaniesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawCompaniesClient + """ + return self._raw_client + + async def search(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Dict[str, typing.Any]: + """ + Search for companies by name, industry, or location. Returns matching company profiles with employee count, industry classification, founding date, and headquarters. Use this to find company entity IDs for detailed lookups. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.search(request_options=request_options) + return _response.data + + async def bio(self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Any: + """ + Get comprehensive company profile including description, founding date, headquarters location, employee count, industry classification, and social media profiles. This is the primary endpoint for company overview data. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Any + Company bio retrieved successfully + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.bio( + company_id="019cb8ac-adee-749e-a75e-a1c236f20f72", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.bio(company_id, request_options=request_options) + return _response.data + + async def industries( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get industry classifications including NAICS codes, SIC codes, and industry descriptions. Useful for filtering companies by vertical or sector. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.industries( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.industries(company_id, request_options=request_options) + return _response.data + + async def financials( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get financial statements for public companies including revenue, net income, assets, and liabilities. Returns most recent fiscal year data or specific year if requested. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.financials( + company_id="ody_co_sample_msft", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.financials(company_id, request_options=request_options) + return _response.data + + async def financials_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get most recent financial statements for public companies. Convenience endpoint that automatically returns the latest available fiscal year data. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.financials_recent( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.financials_recent(company_id, request_options=request_options) + return _response.data + + async def financing_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get most recent funding rounds including round type, amount raised, investors, and valuation. Returns detailed information about the latest equity financing event. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.financing_recent( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.financing_recent(company_id, request_options=request_options) + return _response.data + + async def active_investors( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Any: + """ + Get current investors in the company from recent funding rounds. Returns investor names, types, and contact information. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Any + Active investors retrieved successfully + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.active_investors( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.active_investors(company_id, request_options=request_options) + return _response.data + + async def all_investors( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get complete investor history including historical investors from all funding rounds. Returns comprehensive list of all investors who have participated in company financing. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.all_investors( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.all_investors(company_id, request_options=request_options) + return _response.data + + async def deals(self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Any: + """ + Get all deals for a company including funding rounds and acquisitions. Each deal includes the deal type, round name, investors involved, amount raised, and status. Funding rounds are sourced from investor data, while acquisitions are sourced from M&A records. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Any + Company deals retrieved successfully + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.deals( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.deals(company_id, request_options=request_options) + return _response.data + + async def service_providers( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers working with the company including legal counsel, accounting firms, and consultants. Returns firm names, service types, and engagement information. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.service_providers( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.service_providers(company_id, request_options=request_options) + return _response.data + + async def service_providers_deal( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers involved in specific financing deals including investment bankers, legal advisors, and financial consultants. Returns provider details specific to fundraising transactions. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.service_providers_deal( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.service_providers_deal(company_id, request_options=request_options) + return _response.data + + async def debt_financing_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get most recent debt financing rounds including venture debt, credit lines, and loans. Returns lender information, amounts, and terms. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.debt_financing_recent( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.debt_financing_recent(company_id, request_options=request_options) + return _response.data + + async def similar( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get companies similar to this one based on industry, size, and business model. Returns competitor and peer company information with similarity scores. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.similar( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.similar(company_id, request_options=request_options) + return _response.data + + async def social_analytics( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get social media metrics including LinkedIn followers, Twitter engagement, and Facebook presence. Useful for measuring company online visibility and growth. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.social_analytics( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.social_analytics(company_id, request_options=request_options) + return _response.data + + async def vc_exit_predictions( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get predicted likelihood and timeline for company exit events (IPO or acquisition). Will return ML-based exit probability scores and estimated exit valuation ranges when implemented. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.vc_exit_predictions( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.vc_exit_predictions(company_id, request_options=request_options) + return _response.data + + async def updates( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to company profile data. Returns history of changes to company information with timestamps and modified fields. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.companies.updates( + company_id="openai.com", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.updates(company_id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/companies/raw_client.py b/src/runcaptain/companies/raw_client.py new file mode 100644 index 0000000..a549f15 --- /dev/null +++ b/src/runcaptain/companies/raw_client.py @@ -0,0 +1,2062 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.not_implemented_error import NotImplementedError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawCompaniesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def search( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for companies by name, industry, or location. Returns matching company profiles with employee count, industry classification, founding date, and headquarters. Use this to find company entity IDs for detailed lookups. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/companies/search", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def bio( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Any]: + """ + Get comprehensive company profile including description, founding date, headquarters location, employee count, industry classification, and social media profiles. This is the primary endpoint for company overview data. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Any] + Company bio retrieved successfully + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if _response is None or not _response.text.strip(): + return HttpResponse(response=_response, data=None) + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def industries( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get industry classifications including NAICS codes, SIC codes, and industry descriptions. Useful for filtering companies by vertical or sector. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/industries", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def financials( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get financial statements for public companies including revenue, net income, assets, and liabilities. Returns most recent fiscal year data or specific year if requested. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/financials", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def financials_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get most recent financial statements for public companies. Convenience endpoint that automatically returns the latest available fiscal year data. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/financials/recent", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def financing_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get most recent funding rounds including round type, amount raised, investors, and valuation. Returns detailed information about the latest equity financing event. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/financing/recent", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def active_investors( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Any]: + """ + Get current investors in the company from recent funding rounds. Returns investor names, types, and contact information. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Any] + Active investors retrieved successfully + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/active-investors", + method="GET", + request_options=request_options, + ) + try: + if _response is None or not _response.text.strip(): + return HttpResponse(response=_response, data=None) + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def all_investors( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get complete investor history including historical investors from all funding rounds. Returns comprehensive list of all investors who have participated in company financing. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/all-investors", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def deals( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Any]: + """ + Get all deals for a company including funding rounds and acquisitions. Each deal includes the deal type, round name, investors involved, amount raised, and status. Funding rounds are sourced from investor data, while acquisitions are sourced from M&A records. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Any] + Company deals retrieved successfully + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/deals", + method="GET", + request_options=request_options, + ) + try: + if _response is None or not _response.text.strip(): + return HttpResponse(response=_response, data=None) + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def service_providers( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers working with the company including legal counsel, accounting firms, and consultants. Returns firm names, service types, and engagement information. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/service-providers", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def service_providers_deal( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers involved in specific financing deals including investment bankers, legal advisors, and financial consultants. Returns provider details specific to fundraising transactions. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/service-providers/deal", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def debt_financing_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get most recent debt financing rounds including venture debt, credit lines, and loans. Returns lender information, amounts, and terms. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/debt-financing/recent", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def similar( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get companies similar to this one based on industry, size, and business model. Returns competitor and peer company information with similarity scores. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/similar", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def social_analytics( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get social media metrics including LinkedIn followers, Twitter engagement, and Facebook presence. Useful for measuring company online visibility and growth. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/social-analytics", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def vc_exit_predictions( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get predicted likelihood and timeline for company exit events (IPO or acquisition). Will return ML-based exit probability scores and estimated exit valuation ranges when implemented. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/vc-exit-predictions", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def updates( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to company profile data. Returns history of changes to company information with timestamps and modified fields. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawCompaniesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def search( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for companies by name, industry, or location. Returns matching company profiles with employee count, industry classification, founding date, and headquarters. Use this to find company entity IDs for detailed lookups. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/companies/search", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def bio( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Any]: + """ + Get comprehensive company profile including description, founding date, headquarters location, employee count, industry classification, and social media profiles. This is the primary endpoint for company overview data. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Any] + Company bio retrieved successfully + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if _response is None or not _response.text.strip(): + return AsyncHttpResponse(response=_response, data=None) + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def industries( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get industry classifications including NAICS codes, SIC codes, and industry descriptions. Useful for filtering companies by vertical or sector. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/industries", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def financials( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get financial statements for public companies including revenue, net income, assets, and liabilities. Returns most recent fiscal year data or specific year if requested. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/financials", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def financials_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get most recent financial statements for public companies. Convenience endpoint that automatically returns the latest available fiscal year data. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/financials/recent", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def financing_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get most recent funding rounds including round type, amount raised, investors, and valuation. Returns detailed information about the latest equity financing event. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/financing/recent", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def active_investors( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Any]: + """ + Get current investors in the company from recent funding rounds. Returns investor names, types, and contact information. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Any] + Active investors retrieved successfully + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/active-investors", + method="GET", + request_options=request_options, + ) + try: + if _response is None or not _response.text.strip(): + return AsyncHttpResponse(response=_response, data=None) + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def all_investors( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get complete investor history including historical investors from all funding rounds. Returns comprehensive list of all investors who have participated in company financing. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/all-investors", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def deals( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Any]: + """ + Get all deals for a company including funding rounds and acquisitions. Each deal includes the deal type, round name, investors involved, amount raised, and status. Funding rounds are sourced from investor data, while acquisitions are sourced from M&A records. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Any] + Company deals retrieved successfully + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/deals", + method="GET", + request_options=request_options, + ) + try: + if _response is None or not _response.text.strip(): + return AsyncHttpResponse(response=_response, data=None) + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def service_providers( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers working with the company including legal counsel, accounting firms, and consultants. Returns firm names, service types, and engagement information. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/service-providers", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def service_providers_deal( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers involved in specific financing deals including investment bankers, legal advisors, and financial consultants. Returns provider details specific to fundraising transactions. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/service-providers/deal", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def debt_financing_recent( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get most recent debt financing rounds including venture debt, credit lines, and loans. Returns lender information, amounts, and terms. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/debt-financing/recent", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def similar( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get companies similar to this one based on industry, size, and business model. Returns competitor and peer company information with similarity scores. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/similar", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def social_analytics( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get social media metrics including LinkedIn followers, Twitter engagement, and Facebook presence. Useful for measuring company online visibility and growth. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/social-analytics", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def vc_exit_predictions( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get predicted likelihood and timeline for company exit events (IPO or acquisition). Will return ML-based exit probability scores and estimated exit valuation ranges when implemented. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/vc-exit-predictions", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def updates( + self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to company profile data. Returns history of changes to company information with timestamps and modified fields. + + Parameters + ---------- + company_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/companies/{jsonable_encoder(company_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/credit_analysis/__init__.py b/src/runcaptain/credit_analysis/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/credit_analysis/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/credit_analysis/client.py b/src/runcaptain/credit_analysis/client.py new file mode 100644 index 0000000..77704ff --- /dev/null +++ b/src/runcaptain/credit_analysis/client.py @@ -0,0 +1,434 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawCreditAnalysisClient, RawCreditAnalysisClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class CreditAnalysisClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawCreditAnalysisClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawCreditAnalysisClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawCreditAnalysisClient + """ + return self._raw_client + + def news_search( + self, + *, + start_date: typing.Optional[str] = None, + end_date: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for credit-related news and filings including bond issuances, credit rating changes, and default events. Returns matching news with dates, sources, and content. + + Parameters + ---------- + start_date : typing.Optional[str] + Start date (YYYY-MM-DD) + + end_date : typing.Optional[str] + End date (YYYY-MM-DD) + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.credit_analysis.news_search() + """ + _response = self._raw_client.news_search( + start_date=start_date, end_date=end_date, limit=limit, request_options=request_options + ) + return _response.data + + def news_recent(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Dict[str, typing.Any]: + """ + Get most recent credit news and filings. Returns latest credit events, ratings, and bond issuances from the past 30 days. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.credit_analysis.news_recent() + """ + _response = self._raw_client.news_recent(request_options=request_options) + return _response.data + + def news_detail( + self, news_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get detailed credit news article or filing including full text, metadata, and related entities. Returns comprehensive news item with analysis. + + Parameters + ---------- + news_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.credit_analysis.news_detail( + news_id="abc123def456", + ) + """ + _response = self._raw_client.news_detail(news_id, request_options=request_options) + return _response.data + + def news_attachment( + self, news_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Download attachment files associated with credit news including prospectuses, indentures, and rating reports. Returns document files. + + Parameters + ---------- + news_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.credit_analysis.news_attachment( + news_id="abc123def456", + ) + """ + _response = self._raw_client.news_attachment(news_id, request_options=request_options) + return _response.data + + def news_bulk( + self, + *, + queries: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Retrieve multiple credit news articles by ID in a single request. Returns batch results with article details for each requested ID. + + Parameters + ---------- + queries : typing.Optional[typing.Sequence[str]] + List of search queries + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.credit_analysis.news_bulk( + queries=["Apple credit rating", "Tesla debt analysis"], + ) + """ + _response = self._raw_client.news_bulk(queries=queries, request_options=request_options) + return _response.data + + +class AsyncCreditAnalysisClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawCreditAnalysisClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawCreditAnalysisClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawCreditAnalysisClient + """ + return self._raw_client + + async def news_search( + self, + *, + start_date: typing.Optional[str] = None, + end_date: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for credit-related news and filings including bond issuances, credit rating changes, and default events. Returns matching news with dates, sources, and content. + + Parameters + ---------- + start_date : typing.Optional[str] + Start date (YYYY-MM-DD) + + end_date : typing.Optional[str] + End date (YYYY-MM-DD) + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.credit_analysis.news_search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.news_search( + start_date=start_date, end_date=end_date, limit=limit, request_options=request_options + ) + return _response.data + + async def news_recent( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get most recent credit news and filings. Returns latest credit events, ratings, and bond issuances from the past 30 days. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.credit_analysis.news_recent() + + + asyncio.run(main()) + """ + _response = await self._raw_client.news_recent(request_options=request_options) + return _response.data + + async def news_detail( + self, news_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get detailed credit news article or filing including full text, metadata, and related entities. Returns comprehensive news item with analysis. + + Parameters + ---------- + news_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.credit_analysis.news_detail( + news_id="abc123def456", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.news_detail(news_id, request_options=request_options) + return _response.data + + async def news_attachment( + self, news_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Download attachment files associated with credit news including prospectuses, indentures, and rating reports. Returns document files. + + Parameters + ---------- + news_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.credit_analysis.news_attachment( + news_id="abc123def456", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.news_attachment(news_id, request_options=request_options) + return _response.data + + async def news_bulk( + self, + *, + queries: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Retrieve multiple credit news articles by ID in a single request. Returns batch results with article details for each requested ID. + + Parameters + ---------- + queries : typing.Optional[typing.Sequence[str]] + List of search queries + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.credit_analysis.news_bulk( + queries=["Apple credit rating", "Tesla debt analysis"], + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.news_bulk(queries=queries, request_options=request_options) + return _response.data diff --git a/src/runcaptain/credit_analysis/raw_client.py b/src/runcaptain/credit_analysis/raw_client.py new file mode 100644 index 0000000..176b52d --- /dev/null +++ b/src/runcaptain/credit_analysis/raw_client.py @@ -0,0 +1,635 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.not_implemented_error import NotImplementedError +from ..errors.unauthorized_error import UnauthorizedError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawCreditAnalysisClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def news_search( + self, + *, + start_date: typing.Optional[str] = None, + end_date: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for credit-related news and filings including bond issuances, credit rating changes, and default events. Returns matching news with dates, sources, and content. + + Parameters + ---------- + start_date : typing.Optional[str] + Start date (YYYY-MM-DD) + + end_date : typing.Optional[str] + End date (YYYY-MM-DD) + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/credit-analysis/news/search", + method="GET", + params={ + "start_date": start_date, + "end_date": end_date, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def news_recent( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get most recent credit news and filings. Returns latest credit events, ratings, and bond issuances from the past 30 days. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/credit-analysis/news/recent", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def news_detail( + self, news_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get detailed credit news article or filing including full text, metadata, and related entities. Returns comprehensive news item with analysis. + + Parameters + ---------- + news_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/credit-analysis/news/{jsonable_encoder(news_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def news_attachment( + self, news_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Download attachment files associated with credit news including prospectuses, indentures, and rating reports. Returns document files. + + Parameters + ---------- + news_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/credit-analysis/news/{jsonable_encoder(news_id)}/attachment", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def news_bulk( + self, + *, + queries: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Retrieve multiple credit news articles by ID in a single request. Returns batch results with article details for each requested ID. + + Parameters + ---------- + queries : typing.Optional[typing.Sequence[str]] + List of search queries + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/credit-analysis/news/bulk", + method="POST", + json={ + "queries": queries, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawCreditAnalysisClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def news_search( + self, + *, + start_date: typing.Optional[str] = None, + end_date: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for credit-related news and filings including bond issuances, credit rating changes, and default events. Returns matching news with dates, sources, and content. + + Parameters + ---------- + start_date : typing.Optional[str] + Start date (YYYY-MM-DD) + + end_date : typing.Optional[str] + End date (YYYY-MM-DD) + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/credit-analysis/news/search", + method="GET", + params={ + "start_date": start_date, + "end_date": end_date, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def news_recent( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get most recent credit news and filings. Returns latest credit events, ratings, and bond issuances from the past 30 days. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/credit-analysis/news/recent", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def news_detail( + self, news_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get detailed credit news article or filing including full text, metadata, and related entities. Returns comprehensive news item with analysis. + + Parameters + ---------- + news_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/credit-analysis/news/{jsonable_encoder(news_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def news_attachment( + self, news_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Download attachment files associated with credit news including prospectuses, indentures, and rating reports. Returns document files. + + Parameters + ---------- + news_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/credit-analysis/news/{jsonable_encoder(news_id)}/attachment", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def news_bulk( + self, + *, + queries: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Retrieve multiple credit news articles by ID in a single request. Returns batch results with article details for each requested ID. + + Parameters + ---------- + queries : typing.Optional[typing.Sequence[str]] + List of search queries + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/credit-analysis/news/bulk", + method="POST", + json={ + "queries": queries, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/datasets/client.py b/src/runcaptain/datasets/client.py index c9826e9..0deb669 100644 --- a/src/runcaptain/datasets/client.py +++ b/src/runcaptain/datasets/client.py @@ -25,7 +25,12 @@ def with_raw_response(self) -> RawDatasetsClient: return self._raw_client def search_dataset( - self, dataset: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None + self, + dataset: typing.Optional[str], + *, + q: str, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> DatasetSearchResponse: """ Search for articles within a news dataset. @@ -40,6 +45,12 @@ def search_dataset( dataset : typing.Optional[str] The dataset to search. Contact your Account Executive for available datasets. + q : str + Search query + + limit : typing.Optional[int] + Maximum number of results to return (default: 10, max: 100) + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -58,9 +69,10 @@ def search_dataset( ) client.datasets.search_dataset( dataset="dataset_name", + q="climate change policy", ) """ - _response = self._raw_client.search_dataset(dataset, request_options=request_options) + _response = self._raw_client.search_dataset(dataset, q=q, limit=limit, request_options=request_options) return _response.data def get_dataset_article( @@ -125,7 +137,12 @@ def with_raw_response(self) -> AsyncRawDatasetsClient: return self._raw_client async def search_dataset( - self, dataset: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None + self, + dataset: typing.Optional[str], + *, + q: str, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> DatasetSearchResponse: """ Search for articles within a news dataset. @@ -140,6 +157,12 @@ async def search_dataset( dataset : typing.Optional[str] The dataset to search. Contact your Account Executive for available datasets. + q : str + Search query + + limit : typing.Optional[int] + Maximum number of results to return (default: 10, max: 100) + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -163,12 +186,13 @@ async def search_dataset( async def main() -> None: await client.datasets.search_dataset( dataset="dataset_name", + q="climate change policy", ) asyncio.run(main()) """ - _response = await self._raw_client.search_dataset(dataset, request_options=request_options) + _response = await self._raw_client.search_dataset(dataset, q=q, limit=limit, request_options=request_options) return _response.data async def get_dataset_article( diff --git a/src/runcaptain/datasets/raw_client.py b/src/runcaptain/datasets/raw_client.py index 9cd2363..ea1672d 100644 --- a/src/runcaptain/datasets/raw_client.py +++ b/src/runcaptain/datasets/raw_client.py @@ -22,7 +22,12 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper def search_dataset( - self, dataset: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None + self, + dataset: typing.Optional[str], + *, + q: str, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[DatasetSearchResponse]: """ Search for articles within a news dataset. @@ -37,6 +42,12 @@ def search_dataset( dataset : typing.Optional[str] The dataset to search. Contact your Account Executive for available datasets. + q : str + Search query + + limit : typing.Optional[int] + Maximum number of results to return (default: 10, max: 100) + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -48,6 +59,10 @@ def search_dataset( _response = self._client_wrapper.httpx_client.request( f"v2/datasets/{jsonable_encoder(dataset)}/search", method="GET", + params={ + "q": q, + "limit": limit, + }, request_options=request_options, ) try: @@ -208,7 +223,12 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper async def search_dataset( - self, dataset: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None + self, + dataset: typing.Optional[str], + *, + q: str, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[DatasetSearchResponse]: """ Search for articles within a news dataset. @@ -223,6 +243,12 @@ async def search_dataset( dataset : typing.Optional[str] The dataset to search. Contact your Account Executive for available datasets. + q : str + Search query + + limit : typing.Optional[int] + Maximum number of results to return (default: 10, max: 100) + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -234,6 +260,10 @@ async def search_dataset( _response = await self._client_wrapper.httpx_client.request( f"v2/datasets/{jsonable_encoder(dataset)}/search", method="GET", + params={ + "q": q, + "limit": limit, + }, request_options=request_options, ) try: diff --git a/src/runcaptain/deals/__init__.py b/src/runcaptain/deals/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/deals/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/deals/client.py b/src/runcaptain/deals/client.py new file mode 100644 index 0000000..5dbfae2 --- /dev/null +++ b/src/runcaptain/deals/client.py @@ -0,0 +1,995 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawDealsClient, RawDealsClient + + +class DealsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawDealsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawDealsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawDealsClient + """ + return self._raw_client + + def search( + self, + *, + deal_type: typing.Optional[str] = None, + min_amount: typing.Optional[float] = None, + max_amount: typing.Optional[float] = None, + start_date: typing.Optional[str] = None, + end_date: typing.Optional[str] = None, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for funding rounds and deals by company, deal type, amount range, or date. Returns matching transactions with deal type, amount, date, and participants. Use this to find deal entity IDs for detailed lookups. + + Parameters + ---------- + deal_type : typing.Optional[str] + Filter by deal type + + min_amount : typing.Optional[float] + Minimum deal amount + + max_amount : typing.Optional[float] + Maximum deal amount + + start_date : typing.Optional[str] + Start date (YYYY-MM-DD) + + end_date : typing.Optional[str] + End date (YYYY-MM-DD) + + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Results per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.search() + """ + _response = self._raw_client.search( + deal_type=deal_type, + min_amount=min_amount, + max_amount=max_amount, + start_date=start_date, + end_date=end_date, + page=page, + page_size=page_size, + request_options=request_options, + ) + return _response.data + + def bio(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive deal information including amount, type, date, company, and investor participants. This is the primary endpoint for deal overview data. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.bio( + id="deal_openai_0", + ) + """ + _response = self._raw_client.bio(id, request_options=request_options) + return _response.data + + def detailed( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive deal data combining bio, investors, valuation, and terms in a single response. Use this for complete deal intelligence without multiple API calls. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.detailed( + id="deal_openai_0", + ) + """ + _response = self._raw_client.detailed(id, request_options=request_options) + return _response.data + + def investors( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get all investors participating in the deal including lead and follow-on investors. Returns investor names, roles, and investment amounts. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.investors( + id="deal_openai_0", + ) + """ + _response = self._raw_client.investors(id, request_options=request_options) + return _response.data + + def service_providers( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers involved in the deal including legal counsel, investment bankers, and financial advisors. Returns firm names and service types. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.service_providers( + id="deal_openai_0", + ) + """ + _response = self._raw_client.service_providers(id, request_options=request_options) + return _response.data + + def valuation( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get valuation information including pre-money and post-money valuations, equity percentage, and pricing details. Useful for understanding deal economics. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.valuation( + id="deal_openai_0", + ) + """ + _response = self._raw_client.valuation(id, request_options=request_options) + return _response.data + + def stock_info( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get current stock price and market data for the company involved in this deal. Only applicable for public companies. Returns real-time stock quotes and market metrics. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.stock_info( + id="deal_openai_0", + ) + """ + _response = self._raw_client.stock_info(id, request_options=request_options) + return _response.data + + def cap_table( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get capitalization table showing ownership breakdown after the deal. Will return equity ownership percentages, share counts, and investor stakes when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.cap_table( + id="deal_openai_0", + ) + """ + _response = self._raw_client.cap_table(id, request_options=request_options) + return _response.data + + def tranche( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get information about deal tranches and payment schedules for structured financing. Will return tranche amounts, dates, and conditions when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.tranche( + id="deal_openai_0", + ) + """ + _response = self._raw_client.tranche(id, request_options=request_options) + return _response.data + + def debt_lenders( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get lenders participating in debt financing deals. Returns lender names, amounts, and terms for venture debt and credit facilities. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.debt_lenders( + id="deal_openai_0", + ) + """ + _response = self._raw_client.debt_lenders(id, request_options=request_options) + return _response.data + + def multiples( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get valuation multiples for the deal including revenue multiple, EBITDA multiple, and comparable transaction metrics. Will return detailed valuation analysis when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.multiples( + id="deal_openai_0", + ) + """ + _response = self._raw_client.multiples(id, request_options=request_options) + return _response.data + + def updates( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to deal information. Returns history of changes to deal data with timestamps and modified fields. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.deals.updates( + id="deal_openai_0", + ) + """ + _response = self._raw_client.updates(id, request_options=request_options) + return _response.data + + +class AsyncDealsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawDealsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawDealsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawDealsClient + """ + return self._raw_client + + async def search( + self, + *, + deal_type: typing.Optional[str] = None, + min_amount: typing.Optional[float] = None, + max_amount: typing.Optional[float] = None, + start_date: typing.Optional[str] = None, + end_date: typing.Optional[str] = None, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for funding rounds and deals by company, deal type, amount range, or date. Returns matching transactions with deal type, amount, date, and participants. Use this to find deal entity IDs for detailed lookups. + + Parameters + ---------- + deal_type : typing.Optional[str] + Filter by deal type + + min_amount : typing.Optional[float] + Minimum deal amount + + max_amount : typing.Optional[float] + Maximum deal amount + + start_date : typing.Optional[str] + Start date (YYYY-MM-DD) + + end_date : typing.Optional[str] + End date (YYYY-MM-DD) + + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Results per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.search( + deal_type=deal_type, + min_amount=min_amount, + max_amount=max_amount, + start_date=start_date, + end_date=end_date, + page=page, + page_size=page_size, + request_options=request_options, + ) + return _response.data + + async def bio( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive deal information including amount, type, date, company, and investor participants. This is the primary endpoint for deal overview data. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.bio( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.bio(id, request_options=request_options) + return _response.data + + async def detailed( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive deal data combining bio, investors, valuation, and terms in a single response. Use this for complete deal intelligence without multiple API calls. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.detailed( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.detailed(id, request_options=request_options) + return _response.data + + async def investors( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get all investors participating in the deal including lead and follow-on investors. Returns investor names, roles, and investment amounts. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.investors( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.investors(id, request_options=request_options) + return _response.data + + async def service_providers( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers involved in the deal including legal counsel, investment bankers, and financial advisors. Returns firm names and service types. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.service_providers( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.service_providers(id, request_options=request_options) + return _response.data + + async def valuation( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get valuation information including pre-money and post-money valuations, equity percentage, and pricing details. Useful for understanding deal economics. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.valuation( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.valuation(id, request_options=request_options) + return _response.data + + async def stock_info( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get current stock price and market data for the company involved in this deal. Only applicable for public companies. Returns real-time stock quotes and market metrics. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.stock_info( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.stock_info(id, request_options=request_options) + return _response.data + + async def cap_table( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get capitalization table showing ownership breakdown after the deal. Will return equity ownership percentages, share counts, and investor stakes when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.cap_table( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.cap_table(id, request_options=request_options) + return _response.data + + async def tranche( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get information about deal tranches and payment schedules for structured financing. Will return tranche amounts, dates, and conditions when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.tranche( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.tranche(id, request_options=request_options) + return _response.data + + async def debt_lenders( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get lenders participating in debt financing deals. Returns lender names, amounts, and terms for venture debt and credit facilities. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.debt_lenders( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.debt_lenders(id, request_options=request_options) + return _response.data + + async def multiples( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get valuation multiples for the deal including revenue multiple, EBITDA multiple, and comparable transaction metrics. Will return detailed valuation analysis when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.multiples( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.multiples(id, request_options=request_options) + return _response.data + + async def updates( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to deal information. Returns history of changes to deal data with timestamps and modified fields. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.deals.updates( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.updates(id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/deals/raw_client.py b/src/runcaptain/deals/raw_client.py new file mode 100644 index 0000000..5c852af --- /dev/null +++ b/src/runcaptain/deals/raw_client.py @@ -0,0 +1,1626 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.not_implemented_error import NotImplementedError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawDealsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def search( + self, + *, + deal_type: typing.Optional[str] = None, + min_amount: typing.Optional[float] = None, + max_amount: typing.Optional[float] = None, + start_date: typing.Optional[str] = None, + end_date: typing.Optional[str] = None, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for funding rounds and deals by company, deal type, amount range, or date. Returns matching transactions with deal type, amount, date, and participants. Use this to find deal entity IDs for detailed lookups. + + Parameters + ---------- + deal_type : typing.Optional[str] + Filter by deal type + + min_amount : typing.Optional[float] + Minimum deal amount + + max_amount : typing.Optional[float] + Maximum deal amount + + start_date : typing.Optional[str] + Start date (YYYY-MM-DD) + + end_date : typing.Optional[str] + End date (YYYY-MM-DD) + + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Results per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/deals/search", + method="GET", + params={ + "deal_type": deal_type, + "min_amount": min_amount, + "max_amount": max_amount, + "start_date": start_date, + "end_date": end_date, + "page": page, + "page_size": page_size, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def bio( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive deal information including amount, type, date, company, and investor participants. This is the primary endpoint for deal overview data. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def detailed( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive deal data combining bio, investors, valuation, and terms in a single response. Use this for complete deal intelligence without multiple API calls. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/detailed", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def investors( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get all investors participating in the deal including lead and follow-on investors. Returns investor names, roles, and investment amounts. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/investors", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def service_providers( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers involved in the deal including legal counsel, investment bankers, and financial advisors. Returns firm names and service types. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/service-providers", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def valuation( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get valuation information including pre-money and post-money valuations, equity percentage, and pricing details. Useful for understanding deal economics. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/valuation", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def stock_info( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get current stock price and market data for the company involved in this deal. Only applicable for public companies. Returns real-time stock quotes and market metrics. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/stock-info", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def cap_table( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get capitalization table showing ownership breakdown after the deal. Will return equity ownership percentages, share counts, and investor stakes when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/cap-table", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def tranche( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get information about deal tranches and payment schedules for structured financing. Will return tranche amounts, dates, and conditions when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/tranche", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def debt_lenders( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get lenders participating in debt financing deals. Returns lender names, amounts, and terms for venture debt and credit facilities. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/debt-lenders", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def multiples( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get valuation multiples for the deal including revenue multiple, EBITDA multiple, and comparable transaction metrics. Will return detailed valuation analysis when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/multiples", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def updates( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to deal information. Returns history of changes to deal data with timestamps and modified fields. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawDealsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def search( + self, + *, + deal_type: typing.Optional[str] = None, + min_amount: typing.Optional[float] = None, + max_amount: typing.Optional[float] = None, + start_date: typing.Optional[str] = None, + end_date: typing.Optional[str] = None, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for funding rounds and deals by company, deal type, amount range, or date. Returns matching transactions with deal type, amount, date, and participants. Use this to find deal entity IDs for detailed lookups. + + Parameters + ---------- + deal_type : typing.Optional[str] + Filter by deal type + + min_amount : typing.Optional[float] + Minimum deal amount + + max_amount : typing.Optional[float] + Maximum deal amount + + start_date : typing.Optional[str] + Start date (YYYY-MM-DD) + + end_date : typing.Optional[str] + End date (YYYY-MM-DD) + + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Results per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/deals/search", + method="GET", + params={ + "deal_type": deal_type, + "min_amount": min_amount, + "max_amount": max_amount, + "start_date": start_date, + "end_date": end_date, + "page": page, + "page_size": page_size, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def bio( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive deal information including amount, type, date, company, and investor participants. This is the primary endpoint for deal overview data. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def detailed( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive deal data combining bio, investors, valuation, and terms in a single response. Use this for complete deal intelligence without multiple API calls. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/detailed", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def investors( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get all investors participating in the deal including lead and follow-on investors. Returns investor names, roles, and investment amounts. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/investors", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def service_providers( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers involved in the deal including legal counsel, investment bankers, and financial advisors. Returns firm names and service types. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/service-providers", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def valuation( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get valuation information including pre-money and post-money valuations, equity percentage, and pricing details. Useful for understanding deal economics. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/valuation", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def stock_info( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get current stock price and market data for the company involved in this deal. Only applicable for public companies. Returns real-time stock quotes and market metrics. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/stock-info", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def cap_table( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get capitalization table showing ownership breakdown after the deal. Will return equity ownership percentages, share counts, and investor stakes when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/cap-table", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def tranche( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get information about deal tranches and payment schedules for structured financing. Will return tranche amounts, dates, and conditions when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/tranche", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def debt_lenders( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get lenders participating in debt financing deals. Returns lender names, amounts, and terms for venture debt and credit facilities. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/debt-lenders", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def multiples( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get valuation multiples for the deal including revenue multiple, EBITDA multiple, and comparable transaction metrics. Will return detailed valuation analysis when implemented. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/multiples", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def updates( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to deal information. Returns history of changes to deal data with timestamps and modified fields. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/deals/{jsonable_encoder(id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/errors/__init__.py b/src/runcaptain/errors/__init__.py index ce42490..948df85 100644 --- a/src/runcaptain/errors/__init__.py +++ b/src/runcaptain/errors/__init__.py @@ -10,6 +10,7 @@ from .conflict_error import ConflictError from .forbidden_error import ForbiddenError from .not_found_error import NotFoundError + from .not_implemented_error import NotImplementedError from .service_unavailable_error import ServiceUnavailableError from .unauthorized_error import UnauthorizedError _dynamic_imports: typing.Dict[str, str] = { @@ -17,6 +18,7 @@ "ConflictError": ".conflict_error", "ForbiddenError": ".forbidden_error", "NotFoundError": ".not_found_error", + "NotImplementedError": ".not_implemented_error", "ServiceUnavailableError": ".service_unavailable_error", "UnauthorizedError": ".unauthorized_error", } @@ -48,6 +50,7 @@ def __dir__(): "ConflictError", "ForbiddenError", "NotFoundError", + "NotImplementedError", "ServiceUnavailableError", "UnauthorizedError", ] diff --git a/src/runcaptain/errors/not_implemented_error.py b/src/runcaptain/errors/not_implemented_error.py new file mode 100644 index 0000000..2a7e046 --- /dev/null +++ b/src/runcaptain/errors/not_implemented_error.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.api_error import ApiError + + +class NotImplementedError(ApiError): + def __init__(self, body: typing.Any, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=501, headers=headers, body=body) diff --git a/src/runcaptain/fundamentals/__init__.py b/src/runcaptain/fundamentals/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/fundamentals/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/fundamentals/client.py b/src/runcaptain/fundamentals/client.py new file mode 100644 index 0000000..c17c165 --- /dev/null +++ b/src/runcaptain/fundamentals/client.py @@ -0,0 +1,239 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawFundamentalsClient, RawFundamentalsClient + + +class FundamentalsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawFundamentalsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawFundamentalsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawFundamentalsClient + """ + return self._raw_client + + def sandbox(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Dict[str, typing.Any]: + """ + Get sample entities for testing and development. Returns mock company, person, investor, and fund data for sandbox environment testing. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.fundamentals.sandbox() + """ + _response = self._raw_client.sandbox(request_options=request_options) + return _response.data + + def lookup_tables(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Dict[str, typing.Any]: + """ + Get available reference lookup tables including industry codes, country codes, and entity type classifications. Returns list of available tables with descriptions. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.fundamentals.lookup_tables() + """ + _response = self._raw_client.lookup_tables(request_options=request_options) + return _response.data + + def lookup_table_values( + self, table_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get values from a specific lookup table. Returns table data with codes, descriptions, and hierarchical relationships for reference data. + + Parameters + ---------- + table_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.fundamentals.lookup_table_values( + table_id="sectors", + ) + """ + _response = self._raw_client.lookup_table_values(table_id, request_options=request_options) + return _response.data + + +class AsyncFundamentalsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawFundamentalsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawFundamentalsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawFundamentalsClient + """ + return self._raw_client + + async def sandbox(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Dict[str, typing.Any]: + """ + Get sample entities for testing and development. Returns mock company, person, investor, and fund data for sandbox environment testing. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.fundamentals.sandbox() + + + asyncio.run(main()) + """ + _response = await self._raw_client.sandbox(request_options=request_options) + return _response.data + + async def lookup_tables( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get available reference lookup tables including industry codes, country codes, and entity type classifications. Returns list of available tables with descriptions. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.fundamentals.lookup_tables() + + + asyncio.run(main()) + """ + _response = await self._raw_client.lookup_tables(request_options=request_options) + return _response.data + + async def lookup_table_values( + self, table_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get values from a specific lookup table. Returns table data with codes, descriptions, and hierarchical relationships for reference data. + + Parameters + ---------- + table_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.fundamentals.lookup_table_values( + table_id="sectors", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.lookup_table_values(table_id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/fundamentals/raw_client.py b/src/runcaptain/fundamentals/raw_client.py new file mode 100644 index 0000000..10ce990 --- /dev/null +++ b/src/runcaptain/fundamentals/raw_client.py @@ -0,0 +1,331 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawFundamentalsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def sandbox( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get sample entities for testing and development. Returns mock company, person, investor, and fund data for sandbox environment testing. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/fundamentals/sandbox", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lookup_tables( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get available reference lookup tables including industry codes, country codes, and entity type classifications. Returns list of available tables with descriptions. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/fundamentals/lookup-tables", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lookup_table_values( + self, table_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get values from a specific lookup table. Returns table data with codes, descriptions, and hierarchical relationships for reference data. + + Parameters + ---------- + table_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/fundamentals/lookup-tables/{jsonable_encoder(table_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawFundamentalsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def sandbox( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get sample entities for testing and development. Returns mock company, person, investor, and fund data for sandbox environment testing. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/fundamentals/sandbox", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lookup_tables( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get available reference lookup tables including industry codes, country codes, and entity type classifications. Returns list of available tables with descriptions. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/fundamentals/lookup-tables", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lookup_table_values( + self, table_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get values from a specific lookup table. Returns table data with codes, descriptions, and hierarchical relationships for reference data. + + Parameters + ---------- + table_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/fundamentals/lookup-tables/{jsonable_encoder(table_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/funds/__init__.py b/src/runcaptain/funds/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/funds/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/funds/client.py b/src/runcaptain/funds/client.py new file mode 100644 index 0000000..d6c51ff --- /dev/null +++ b/src/runcaptain/funds/client.py @@ -0,0 +1,867 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawFundsClient, RawFundsClient + + +class FundsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawFundsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawFundsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawFundsClient + """ + return self._raw_client + + def search( + self, + *, + vintage_year: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for venture capital and private equity funds by name. Returns matching fund profiles with size, vintage year, and investment focus. Use this to find fund entity IDs for detailed lookups. + + Parameters + ---------- + vintage_year : typing.Optional[int] + Filter by vintage year + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.search() + """ + _response = self._raw_client.search(vintage_year=vintage_year, limit=limit, request_options=request_options) + return _response.data + + def bio( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive fund profile including fund size, vintage year, investment strategy, stage focus, and sector focus. This is the primary endpoint for fund overview data. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.bio( + fund_id="sequoia", + ) + """ + _response = self._raw_client.bio(fund_id, request_options=request_options) + return _response.data + + def performance( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get fund performance metrics including IRR, TVPI, DPI, and RVPI. Will return LP-level performance data when implemented with proprietary fund reporting. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.performance( + fund_id="sequoia", + ) + """ + _response = self._raw_client.performance(fund_id, request_options=request_options) + return _response.data + + def active_investments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get current portfolio companies invested by this specific fund. Returns company names, investment amounts, and current status. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.active_investments( + fund_id="sequoia", + ) + """ + _response = self._raw_client.active_investments(fund_id, request_options=request_options) + return _response.data + + def all_investments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get complete investment history for this specific fund including current and exited positions. Returns all companies backed by the fund with outcomes. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.all_investments( + fund_id="sequoia", + ) + """ + _response = self._raw_client.all_investments(fund_id, request_options=request_options) + return _response.data + + def commitments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get limited partner commitments to the fund including LP names and commitment amounts. Returns investor base and capital structure. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.commitments( + fund_id="sequoia", + ) + """ + _response = self._raw_client.commitments(fund_id, request_options=request_options) + return _response.data + + def cash_flows( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get fund cash flow history including capital calls and distributions. Will return quarterly cash flow statements when implemented with LP reporting data. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.cash_flows( + fund_id="sequoia", + ) + """ + _response = self._raw_client.cash_flows(fund_id, request_options=request_options) + return _response.data + + def benchmark( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get fund performance compared to industry benchmarks and peer funds. Will return quartile rankings and comparative metrics when implemented. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.benchmark( + fund_id="sequoia", + ) + """ + _response = self._raw_client.benchmark(fund_id, request_options=request_options) + return _response.data + + def people( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get investment team members for the fund including partners, principals, and associates. Returns names, titles, and LinkedIn profiles. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.people( + fund_id="sequoia", + ) + """ + _response = self._raw_client.people(fund_id, request_options=request_options) + return _response.data + + def preferences( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get investment criteria and preferences for the fund including stage focus, sector preferences, geography, and check size ranges. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.preferences( + fund_id="sequoia", + ) + """ + _response = self._raw_client.preferences(fund_id, request_options=request_options) + return _response.data + + def updates( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to fund profile data. Returns history of changes including new investments, exits, and team changes with timestamps. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.funds.updates( + fund_id="sequoia", + ) + """ + _response = self._raw_client.updates(fund_id, request_options=request_options) + return _response.data + + +class AsyncFundsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawFundsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawFundsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawFundsClient + """ + return self._raw_client + + async def search( + self, + *, + vintage_year: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for venture capital and private equity funds by name. Returns matching fund profiles with size, vintage year, and investment focus. Use this to find fund entity IDs for detailed lookups. + + Parameters + ---------- + vintage_year : typing.Optional[int] + Filter by vintage year + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.search( + vintage_year=vintage_year, limit=limit, request_options=request_options + ) + return _response.data + + async def bio( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive fund profile including fund size, vintage year, investment strategy, stage focus, and sector focus. This is the primary endpoint for fund overview data. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.bio( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.bio(fund_id, request_options=request_options) + return _response.data + + async def performance( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get fund performance metrics including IRR, TVPI, DPI, and RVPI. Will return LP-level performance data when implemented with proprietary fund reporting. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.performance( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.performance(fund_id, request_options=request_options) + return _response.data + + async def active_investments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get current portfolio companies invested by this specific fund. Returns company names, investment amounts, and current status. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.active_investments( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.active_investments(fund_id, request_options=request_options) + return _response.data + + async def all_investments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get complete investment history for this specific fund including current and exited positions. Returns all companies backed by the fund with outcomes. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.all_investments( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.all_investments(fund_id, request_options=request_options) + return _response.data + + async def commitments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get limited partner commitments to the fund including LP names and commitment amounts. Returns investor base and capital structure. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.commitments( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.commitments(fund_id, request_options=request_options) + return _response.data + + async def cash_flows( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get fund cash flow history including capital calls and distributions. Will return quarterly cash flow statements when implemented with LP reporting data. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.cash_flows( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.cash_flows(fund_id, request_options=request_options) + return _response.data + + async def benchmark( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Coming Soon: Get fund performance compared to industry benchmarks and peer funds. Will return quartile rankings and comparative metrics when implemented. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.benchmark( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.benchmark(fund_id, request_options=request_options) + return _response.data + + async def people( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get investment team members for the fund including partners, principals, and associates. Returns names, titles, and LinkedIn profiles. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.people( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.people(fund_id, request_options=request_options) + return _response.data + + async def preferences( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get investment criteria and preferences for the fund including stage focus, sector preferences, geography, and check size ranges. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.preferences( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.preferences(fund_id, request_options=request_options) + return _response.data + + async def updates( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to fund profile data. Returns history of changes including new investments, exits, and team changes with timestamps. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.funds.updates( + fund_id="sequoia", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.updates(fund_id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/funds/raw_client.py b/src/runcaptain/funds/raw_client.py new file mode 100644 index 0000000..fe6981f --- /dev/null +++ b/src/runcaptain/funds/raw_client.py @@ -0,0 +1,1456 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.not_implemented_error import NotImplementedError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawFundsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def search( + self, + *, + vintage_year: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for venture capital and private equity funds by name. Returns matching fund profiles with size, vintage year, and investment focus. Use this to find fund entity IDs for detailed lookups. + + Parameters + ---------- + vintage_year : typing.Optional[int] + Filter by vintage year + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/funds/search", + method="GET", + params={ + "vintage_year": vintage_year, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def bio( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive fund profile including fund size, vintage year, investment strategy, stage focus, and sector focus. This is the primary endpoint for fund overview data. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def performance( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get fund performance metrics including IRR, TVPI, DPI, and RVPI. Will return LP-level performance data when implemented with proprietary fund reporting. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/performance", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def active_investments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get current portfolio companies invested by this specific fund. Returns company names, investment amounts, and current status. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/active-investments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def all_investments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get complete investment history for this specific fund including current and exited positions. Returns all companies backed by the fund with outcomes. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/all-investments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def commitments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get limited partner commitments to the fund including LP names and commitment amounts. Returns investor base and capital structure. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/commitments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def cash_flows( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get fund cash flow history including capital calls and distributions. Will return quarterly cash flow statements when implemented with LP reporting data. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/cash-flows", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def benchmark( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get fund performance compared to industry benchmarks and peer funds. Will return quartile rankings and comparative metrics when implemented. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/benchmark", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def people( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get investment team members for the fund including partners, principals, and associates. Returns names, titles, and LinkedIn profiles. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/people", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def preferences( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get investment criteria and preferences for the fund including stage focus, sector preferences, geography, and check size ranges. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/preferences", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def updates( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to fund profile data. Returns history of changes including new investments, exits, and team changes with timestamps. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawFundsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def search( + self, + *, + vintage_year: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for venture capital and private equity funds by name. Returns matching fund profiles with size, vintage year, and investment focus. Use this to find fund entity IDs for detailed lookups. + + Parameters + ---------- + vintage_year : typing.Optional[int] + Filter by vintage year + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/funds/search", + method="GET", + params={ + "vintage_year": vintage_year, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def bio( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive fund profile including fund size, vintage year, investment strategy, stage focus, and sector focus. This is the primary endpoint for fund overview data. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def performance( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get fund performance metrics including IRR, TVPI, DPI, and RVPI. Will return LP-level performance data when implemented with proprietary fund reporting. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/performance", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def active_investments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get current portfolio companies invested by this specific fund. Returns company names, investment amounts, and current status. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/active-investments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def all_investments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get complete investment history for this specific fund including current and exited positions. Returns all companies backed by the fund with outcomes. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/all-investments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def commitments( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get limited partner commitments to the fund including LP names and commitment amounts. Returns investor base and capital structure. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/commitments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def cash_flows( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get fund cash flow history including capital calls and distributions. Will return quarterly cash flow statements when implemented with LP reporting data. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/cash-flows", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def benchmark( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Coming Soon: Get fund performance compared to industry benchmarks and peer funds. Will return quartile rankings and comparative metrics when implemented. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/benchmark", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def people( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get investment team members for the fund including partners, principals, and associates. Returns names, titles, and LinkedIn profiles. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/people", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def preferences( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get investment criteria and preferences for the fund including stage focus, sector preferences, geography, and check size ranges. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/preferences", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def updates( + self, fund_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to fund profile data. Returns history of changes including new investments, exits, and team changes with timestamps. + + Parameters + ---------- + fund_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/funds/{jsonable_encoder(fund_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/general/__init__.py b/src/runcaptain/general/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/general/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/general/client.py b/src/runcaptain/general/client.py new file mode 100644 index 0000000..97f03b0 --- /dev/null +++ b/src/runcaptain/general/client.py @@ -0,0 +1,545 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawGeneralClient, RawGeneralClient + + +class GeneralClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawGeneralClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawGeneralClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawGeneralClient + """ + return self._raw_client + + def search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Search across all entity types (companies, people, investors, funds, deals, etc.) in a unified query. Returns matching entities with their type and basic information. Use this for broad discovery before drilling into specific entity types. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.general.search() + """ + _response = self._raw_client.search(limit=limit, request_options=request_options) + return _response.data + + def search_shared(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Dict[str, typing.Any]: + """ + Search for entities shared across your organization. Returns entities that multiple team members have accessed or tagged. Useful for discovering commonly referenced companies, investors, or people within your team. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.general.search_shared() + """ + _response = self._raw_client.search_shared(request_options=request_options) + return _response.data + + def entity_people( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get people associated with any entity (company employees, fund team members, investor partners, etc.). Returns names, titles, and LinkedIn profiles for key people. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.general.entity_people( + entity_id="openai", + ) + """ + _response = self._raw_client.entity_people(entity_id, request_options=request_options) + return _response.data + + def entity_locations( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get office locations for any entity. Returns headquarters and branch office addresses with city, state, country, and full address details. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.general.entity_locations( + entity_id="openai", + ) + """ + _response = self._raw_client.entity_locations(entity_id, request_options=request_options) + return _response.data + + def entity_affiliates( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get affiliated entities and subsidiaries for any entity. Returns parent companies, subsidiaries, and related entities with ownership information. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.general.entity_affiliates( + entity_id="openai", + ) + """ + _response = self._raw_client.entity_affiliates(entity_id, request_options=request_options) + return _response.data + + def entity_news( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get recent news articles and mentions for any entity. Returns article titles, URLs, sources, publication dates, and snippets. Useful for tracking announcements, funding news, and company updates. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.general.entity_news( + entity_id="openai", + ) + """ + _response = self._raw_client.entity_news(entity_id, request_options=request_options) + return _response.data + + def entity_updates( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of data updates for any entity. Returns history of changes to the entity's profile, tracking when information was added or modified. Useful for monitoring data freshness. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.general.entity_updates( + entity_id="openai", + ) + """ + _response = self._raw_client.entity_updates(entity_id, request_options=request_options) + return _response.data + + +class AsyncGeneralClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawGeneralClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawGeneralClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawGeneralClient + """ + return self._raw_client + + async def search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Search across all entity types (companies, people, investors, funds, deals, etc.) in a unified query. Returns matching entities with their type and basic information. Use this for broad discovery before drilling into specific entity types. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.general.search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.search(limit=limit, request_options=request_options) + return _response.data + + async def search_shared( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Search for entities shared across your organization. Returns entities that multiple team members have accessed or tagged. Useful for discovering commonly referenced companies, investors, or people within your team. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.general.search_shared() + + + asyncio.run(main()) + """ + _response = await self._raw_client.search_shared(request_options=request_options) + return _response.data + + async def entity_people( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get people associated with any entity (company employees, fund team members, investor partners, etc.). Returns names, titles, and LinkedIn profiles for key people. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.general.entity_people( + entity_id="openai", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.entity_people(entity_id, request_options=request_options) + return _response.data + + async def entity_locations( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get office locations for any entity. Returns headquarters and branch office addresses with city, state, country, and full address details. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.general.entity_locations( + entity_id="openai", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.entity_locations(entity_id, request_options=request_options) + return _response.data + + async def entity_affiliates( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get affiliated entities and subsidiaries for any entity. Returns parent companies, subsidiaries, and related entities with ownership information. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.general.entity_affiliates( + entity_id="openai", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.entity_affiliates(entity_id, request_options=request_options) + return _response.data + + async def entity_news( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get recent news articles and mentions for any entity. Returns article titles, URLs, sources, publication dates, and snippets. Useful for tracking announcements, funding news, and company updates. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.general.entity_news( + entity_id="openai", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.entity_news(entity_id, request_options=request_options) + return _response.data + + async def entity_updates( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of data updates for any entity. Returns history of changes to the entity's profile, tracking when information was added or modified. Useful for monitoring data freshness. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.general.entity_updates( + entity_id="openai", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.entity_updates(entity_id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/general/raw_client.py b/src/runcaptain/general/raw_client.py new file mode 100644 index 0000000..1fdcf48 --- /dev/null +++ b/src/runcaptain/general/raw_client.py @@ -0,0 +1,823 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawGeneralClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search across all entity types (companies, people, investors, funds, deals, etc.) in a unified query. Returns matching entities with their type and basic information. Use this for broad discovery before drilling into specific entity types. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/general/search", + method="GET", + params={ + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def search_shared( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for entities shared across your organization. Returns entities that multiple team members have accessed or tagged. Useful for discovering commonly referenced companies, investors, or people within your team. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/general/search/shared", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def entity_people( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get people associated with any entity (company employees, fund team members, investor partners, etc.). Returns names, titles, and LinkedIn profiles for key people. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/people", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def entity_locations( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get office locations for any entity. Returns headquarters and branch office addresses with city, state, country, and full address details. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/locations", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def entity_affiliates( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get affiliated entities and subsidiaries for any entity. Returns parent companies, subsidiaries, and related entities with ownership information. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/affiliates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def entity_news( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get recent news articles and mentions for any entity. Returns article titles, URLs, sources, publication dates, and snippets. Useful for tracking announcements, funding news, and company updates. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/news", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def entity_updates( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of data updates for any entity. Returns history of changes to the entity's profile, tracking when information was added or modified. Useful for monitoring data freshness. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawGeneralClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search across all entity types (companies, people, investors, funds, deals, etc.) in a unified query. Returns matching entities with their type and basic information. Use this for broad discovery before drilling into specific entity types. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/general/search", + method="GET", + params={ + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def search_shared( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for entities shared across your organization. Returns entities that multiple team members have accessed or tagged. Useful for discovering commonly referenced companies, investors, or people within your team. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/general/search/shared", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def entity_people( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get people associated with any entity (company employees, fund team members, investor partners, etc.). Returns names, titles, and LinkedIn profiles for key people. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/people", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def entity_locations( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get office locations for any entity. Returns headquarters and branch office addresses with city, state, country, and full address details. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/locations", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def entity_affiliates( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get affiliated entities and subsidiaries for any entity. Returns parent companies, subsidiaries, and related entities with ownership information. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/affiliates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def entity_news( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get recent news articles and mentions for any entity. Returns article titles, URLs, sources, publication dates, and snippets. Useful for tracking announcements, funding news, and company updates. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/news", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def entity_updates( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of data updates for any entity. Returns history of changes to the entity's profile, tracking when information was added or modified. Useful for monitoring data freshness. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/general/{jsonable_encoder(entity_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/indexing/client.py b/src/runcaptain/indexing/client.py index 91fed1a..b0824bd 100644 --- a/src/runcaptain/indexing/client.py +++ b/src/runcaptain/indexing/client.py @@ -767,7 +767,7 @@ def index_r2bucket_v2( request_options: typing.Optional[RequestOptions] = None, ) -> IndexJobResponseV2: """ - Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}. + Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}. Parameters ---------- @@ -1034,8 +1034,8 @@ def index_url_v2( Index documents from public URLs into a collection. No cloud storage credentials required. You can provide either: - - `url` — a single URL string for one document - - `urls` — an array of URL strings for multiple documents + - `url` — a single URL string for one document + - `urls` — an array of URL strings for multiple documents Supported file types: PDF, DOCX, DOC, XLSX, XLS, CSV, TSV, TXT, MD, JSON, YAML, YML, PNG, JPG, JPEG, GIF, BMP, TIFF. Documents are downloaded and processed through the same pipeline as cloud storage indexing. @@ -1902,7 +1902,7 @@ async def index_r2bucket_v2( request_options: typing.Optional[RequestOptions] = None, ) -> IndexJobResponseV2: """ - Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}. + Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}. Parameters ---------- @@ -2193,8 +2193,8 @@ async def index_url_v2( Index documents from public URLs into a collection. No cloud storage credentials required. You can provide either: - - `url` — a single URL string for one document - - `urls` — an array of URL strings for multiple documents + - `url` — a single URL string for one document + - `urls` — an array of URL strings for multiple documents Supported file types: PDF, DOCX, DOC, XLSX, XLS, CSV, TSV, TXT, MD, JSON, YAML, YML, PNG, JPG, JPEG, GIF, BMP, TIFF. Documents are downloaded and processed through the same pipeline as cloud storage indexing. diff --git a/src/runcaptain/indexing/raw_client.py b/src/runcaptain/indexing/raw_client.py index 58745db..27b0a2f 100644 --- a/src/runcaptain/indexing/raw_client.py +++ b/src/runcaptain/indexing/raw_client.py @@ -789,7 +789,7 @@ def index_r2bucket_v2( request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[IndexJobResponseV2]: """ - Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}. + Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}. Parameters ---------- @@ -1063,8 +1063,8 @@ def index_url_v2( Index documents from public URLs into a collection. No cloud storage credentials required. You can provide either: - - `url` — a single URL string for one document - - `urls` — an array of URL strings for multiple documents + - `url` — a single URL string for one document + - `urls` — an array of URL strings for multiple documents Supported file types: PDF, DOCX, DOC, XLSX, XLS, CSV, TSV, TXT, MD, JSON, YAML, YML, PNG, JPG, JPEG, GIF, BMP, TIFF. Documents are downloaded and processed through the same pipeline as cloud storage indexing. @@ -1883,7 +1883,7 @@ async def index_r2bucket_v2( request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[IndexJobResponseV2]: """ - Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}. + Index all files from a Cloudflare R2 bucket into a collection. R2 is S3-compatible — provide your R2 API token's Access Key ID and Secret Access Key. Returns a job_id for tracking progress via GET /v2/jobs/{job_id}. Parameters ---------- @@ -2157,8 +2157,8 @@ async def index_url_v2( Index documents from public URLs into a collection. No cloud storage credentials required. You can provide either: - - `url` — a single URL string for one document - - `urls` — an array of URL strings for multiple documents + - `url` — a single URL string for one document + - `urls` — an array of URL strings for multiple documents Supported file types: PDF, DOCX, DOC, XLSX, XLS, CSV, TSV, TXT, MD, JSON, YAML, YML, PNG, JPG, JPEG, GIF, BMP, TIFF. Documents are downloaded and processed through the same pipeline as cloud storage indexing. diff --git a/src/runcaptain/investors/__init__.py b/src/runcaptain/investors/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/investors/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/investors/client.py b/src/runcaptain/investors/client.py new file mode 100644 index 0000000..571f1ea --- /dev/null +++ b/src/runcaptain/investors/client.py @@ -0,0 +1,863 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawInvestorsClient, RawInvestorsClient + + +class InvestorsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawInvestorsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawInvestorsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawInvestorsClient + """ + return self._raw_client + + def search( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for venture capital firms, angel investors, and institutional investors by name. Returns matching investor profiles with investment focus, portfolio size, and notable investments. Use this to find investor entity IDs for detailed lookups. + + Parameters + ---------- + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Results per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.search() + """ + _response = self._raw_client.search(page=page, page_size=page_size, request_options=request_options) + return _response.data + + def bio(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive investor profile including description, investment thesis, stage focus, sector focus, and notable portfolio companies. This is the primary endpoint for investor overview data. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.bio( + id="ody_inv_019cb8ac-g789-749e-a75e-h7i880j64d16", + ) + """ + _response = self._raw_client.bio(id, request_options=request_options) + return _response.data + + def active_investments( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get current portfolio companies that the investor has active positions in. Returns company names, investment dates, and current status. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.active_investments( + id="deal_openai_0", + ) + """ + _response = self._raw_client.active_investments(id, request_options=request_options) + return _response.data + + def all_investments( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get complete investment history including current portfolio and exited positions. Returns all companies the investor has backed with investment details and outcomes. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.all_investments( + id="deal_openai_0", + ) + """ + _response = self._raw_client.all_investments(id, request_options=request_options) + return _response.data + + def preferences( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get investment preferences including stage focus, sector preferences, geography, and typical check size. Useful for determining investment fit. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.preferences( + id="deal_openai_0", + ) + """ + _response = self._raw_client.preferences(id, request_options=request_options) + return _response.data + + def funds( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get all funds managed by the investor including fund names, sizes, vintage years, and status. Returns complete fund portfolio for multi-fund investors. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.funds( + id="deal_openai_0", + ) + """ + _response = self._raw_client.funds(id, request_options=request_options) + return _response.data + + def funds_latest( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get information about the investor's most recent fund including size, vintage year, and deployment status. Useful for understanding current investment capacity. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.funds_latest( + id="deal_openai_0", + ) + """ + _response = self._raw_client.funds_latest(id, request_options=request_options) + return _response.data + + def board_seats( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get board seats held by the investor's team members. Returns companies where investor partners serve on the board of directors. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.board_seats( + id="deal_openai_0", + ) + """ + _response = self._raw_client.board_seats(id, request_options=request_options) + return _response.data + + def service_providers( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers used by the investor including legal counsel, fund administrators, and consultants. Returns firm names and service types. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.service_providers( + id="deal_openai_0", + ) + """ + _response = self._raw_client.service_providers(id, request_options=request_options) + return _response.data + + def service_providers_deal( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers involved in the investor's deal flow including transaction advisors and due diligence firms. Returns provider details specific to deal execution. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.service_providers_deal( + id="deal_openai_0", + ) + """ + _response = self._raw_client.service_providers_deal(id, request_options=request_options) + return _response.data + + def updates( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to investor profile data. Returns history of changes including new investments, fund raises, and team changes with timestamps. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.investors.updates( + id="deal_openai_0", + ) + """ + _response = self._raw_client.updates(id, request_options=request_options) + return _response.data + + +class AsyncInvestorsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawInvestorsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawInvestorsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawInvestorsClient + """ + return self._raw_client + + async def search( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for venture capital firms, angel investors, and institutional investors by name. Returns matching investor profiles with investment focus, portfolio size, and notable investments. Use this to find investor entity IDs for detailed lookups. + + Parameters + ---------- + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Results per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.search(page=page, page_size=page_size, request_options=request_options) + return _response.data + + async def bio( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive investor profile including description, investment thesis, stage focus, sector focus, and notable portfolio companies. This is the primary endpoint for investor overview data. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.bio( + id="ody_inv_019cb8ac-g789-749e-a75e-h7i880j64d16", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.bio(id, request_options=request_options) + return _response.data + + async def active_investments( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get current portfolio companies that the investor has active positions in. Returns company names, investment dates, and current status. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.active_investments( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.active_investments(id, request_options=request_options) + return _response.data + + async def all_investments( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get complete investment history including current portfolio and exited positions. Returns all companies the investor has backed with investment details and outcomes. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.all_investments( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.all_investments(id, request_options=request_options) + return _response.data + + async def preferences( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get investment preferences including stage focus, sector preferences, geography, and typical check size. Useful for determining investment fit. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.preferences( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.preferences(id, request_options=request_options) + return _response.data + + async def funds( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get all funds managed by the investor including fund names, sizes, vintage years, and status. Returns complete fund portfolio for multi-fund investors. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.funds( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.funds(id, request_options=request_options) + return _response.data + + async def funds_latest( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get information about the investor's most recent fund including size, vintage year, and deployment status. Useful for understanding current investment capacity. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.funds_latest( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.funds_latest(id, request_options=request_options) + return _response.data + + async def board_seats( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get board seats held by the investor's team members. Returns companies where investor partners serve on the board of directors. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.board_seats( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.board_seats(id, request_options=request_options) + return _response.data + + async def service_providers( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers used by the investor including legal counsel, fund administrators, and consultants. Returns firm names and service types. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.service_providers( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.service_providers(id, request_options=request_options) + return _response.data + + async def service_providers_deal( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers involved in the investor's deal flow including transaction advisors and due diligence firms. Returns provider details specific to deal execution. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.service_providers_deal( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.service_providers_deal(id, request_options=request_options) + return _response.data + + async def updates( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to investor profile data. Returns history of changes including new investments, fund raises, and team changes with timestamps. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.investors.updates( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.updates(id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/investors/raw_client.py b/src/runcaptain/investors/raw_client.py new file mode 100644 index 0000000..e94956a --- /dev/null +++ b/src/runcaptain/investors/raw_client.py @@ -0,0 +1,1412 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.not_implemented_error import NotImplementedError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawInvestorsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def search( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for venture capital firms, angel investors, and institutional investors by name. Returns matching investor profiles with investment focus, portfolio size, and notable investments. Use this to find investor entity IDs for detailed lookups. + + Parameters + ---------- + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Results per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/investors/search", + method="GET", + params={ + "page": page, + "page_size": page_size, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def bio( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive investor profile including description, investment thesis, stage focus, sector focus, and notable portfolio companies. This is the primary endpoint for investor overview data. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def active_investments( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get current portfolio companies that the investor has active positions in. Returns company names, investment dates, and current status. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/active-investments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def all_investments( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get complete investment history including current portfolio and exited positions. Returns all companies the investor has backed with investment details and outcomes. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/all-investments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def preferences( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get investment preferences including stage focus, sector preferences, geography, and typical check size. Useful for determining investment fit. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/preferences", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def funds( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get all funds managed by the investor including fund names, sizes, vintage years, and status. Returns complete fund portfolio for multi-fund investors. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/funds", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def funds_latest( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get information about the investor's most recent fund including size, vintage year, and deployment status. Useful for understanding current investment capacity. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/funds/latest", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def board_seats( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get board seats held by the investor's team members. Returns companies where investor partners serve on the board of directors. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/board-seats", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def service_providers( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers used by the investor including legal counsel, fund administrators, and consultants. Returns firm names and service types. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/service-providers", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def service_providers_deal( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers involved in the investor's deal flow including transaction advisors and due diligence firms. Returns provider details specific to deal execution. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/service-providers/deal", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def updates( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to investor profile data. Returns history of changes including new investments, fund raises, and team changes with timestamps. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawInvestorsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def search( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for venture capital firms, angel investors, and institutional investors by name. Returns matching investor profiles with investment focus, portfolio size, and notable investments. Use this to find investor entity IDs for detailed lookups. + + Parameters + ---------- + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Results per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/investors/search", + method="GET", + params={ + "page": page, + "page_size": page_size, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def bio( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive investor profile including description, investment thesis, stage focus, sector focus, and notable portfolio companies. This is the primary endpoint for investor overview data. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def active_investments( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get current portfolio companies that the investor has active positions in. Returns company names, investment dates, and current status. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/active-investments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def all_investments( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get complete investment history including current portfolio and exited positions. Returns all companies the investor has backed with investment details and outcomes. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/all-investments", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def preferences( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get investment preferences including stage focus, sector preferences, geography, and typical check size. Useful for determining investment fit. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/preferences", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def funds( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get all funds managed by the investor including fund names, sizes, vintage years, and status. Returns complete fund portfolio for multi-fund investors. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/funds", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def funds_latest( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get information about the investor's most recent fund including size, vintage year, and deployment status. Useful for understanding current investment capacity. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/funds/latest", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def board_seats( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get board seats held by the investor's team members. Returns companies where investor partners serve on the board of directors. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/board-seats", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def service_providers( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers used by the investor including legal counsel, fund administrators, and consultants. Returns firm names and service types. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/service-providers", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def service_providers_deal( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers involved in the investor's deal flow including transaction advisors and due diligence firms. Returns provider details specific to deal execution. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/service-providers/deal", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def updates( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to investor profile data. Returns history of changes including new investments, fund raises, and team changes with timestamps. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/investors/{jsonable_encoder(id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/limited_partners/__init__.py b/src/runcaptain/limited_partners/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/limited_partners/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/limited_partners/client.py b/src/runcaptain/limited_partners/client.py new file mode 100644 index 0000000..51a2dac --- /dev/null +++ b/src/runcaptain/limited_partners/client.py @@ -0,0 +1,703 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawLimitedPartnersClient, RawLimitedPartnersClient + + +class LimitedPartnersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawLimitedPartnersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawLimitedPartnersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawLimitedPartnersClient + """ + return self._raw_client + + def lps_search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Search for institutional limited partners including pension funds, endowments, and family offices. Returns matching LP profiles with total commitments and fund relationships. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.limited_partners.lps_search() + """ + _response = self._raw_client.lps_search(limit=limit, request_options=request_options) + return _response.data + + def lps_bio( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive limited partner profile including institution type, total assets under management, investment strategy, and notable fund commitments. This is the primary endpoint for LP overview data. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.limited_partners.lps_bio( + lp_id="calpers", + ) + """ + _response = self._raw_client.lps_bio(lp_id, request_options=request_options) + return _response.data + + def lps_commitments_detailed( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get detailed fund commitments including specific fund names, commitment amounts, vintage years, and commitment status. Returns complete LP portfolio. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.limited_partners.lps_commitments_detailed( + lp_id="calpers", + ) + """ + _response = self._raw_client.lps_commitments_detailed(lp_id, request_options=request_options) + return _response.data + + def lps_commitments_aggregates( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get aggregated commitment statistics including total commitments by vintage year, fund type, and geography. Returns high-level allocation summary. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.limited_partners.lps_commitments_aggregates( + lp_id="calpers", + ) + """ + _response = self._raw_client.lps_commitments_aggregates(lp_id, request_options=request_options) + return _response.data + + def lps_allocations_target( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get target allocation percentages by asset class, geography, and strategy. Returns investment policy guidelines and target portfolio mix. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.limited_partners.lps_allocations_target( + lp_id="calpers", + ) + """ + _response = self._raw_client.lps_allocations_target(lp_id, request_options=request_options) + return _response.data + + def lps_allocations_actual( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get actual current allocation percentages by asset class, geography, and strategy. Returns real portfolio composition and compare to targets. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.limited_partners.lps_allocations_actual( + lp_id="calpers", + ) + """ + _response = self._raw_client.lps_allocations_actual(lp_id, request_options=request_options) + return _response.data + + def lps_commitment_preferences( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get commitment preferences including preferred fund sizes, vintage year focus, and investment stage preferences. Useful for GP fundraising targeting. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.limited_partners.lps_commitment_preferences( + lp_id="calpers", + ) + """ + _response = self._raw_client.lps_commitment_preferences(lp_id, request_options=request_options) + return _response.data + + def lps_service_providers( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers used by the LP including consultants, custodians, and legal advisors. Returns firm names and service types. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.limited_partners.lps_service_providers( + lp_id="calpers", + ) + """ + _response = self._raw_client.lps_service_providers(lp_id, request_options=request_options) + return _response.data + + def lps_updates( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to LP profile data. Returns history of changes including new commitments, policy changes, and team updates with timestamps. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.limited_partners.lps_updates( + lp_id="calpers", + ) + """ + _response = self._raw_client.lps_updates(lp_id, request_options=request_options) + return _response.data + + +class AsyncLimitedPartnersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawLimitedPartnersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawLimitedPartnersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawLimitedPartnersClient + """ + return self._raw_client + + async def lps_search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Search for institutional limited partners including pension funds, endowments, and family offices. Returns matching LP profiles with total commitments and fund relationships. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.limited_partners.lps_search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.lps_search(limit=limit, request_options=request_options) + return _response.data + + async def lps_bio( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive limited partner profile including institution type, total assets under management, investment strategy, and notable fund commitments. This is the primary endpoint for LP overview data. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.limited_partners.lps_bio( + lp_id="calpers", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.lps_bio(lp_id, request_options=request_options) + return _response.data + + async def lps_commitments_detailed( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get detailed fund commitments including specific fund names, commitment amounts, vintage years, and commitment status. Returns complete LP portfolio. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.limited_partners.lps_commitments_detailed( + lp_id="calpers", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.lps_commitments_detailed(lp_id, request_options=request_options) + return _response.data + + async def lps_commitments_aggregates( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get aggregated commitment statistics including total commitments by vintage year, fund type, and geography. Returns high-level allocation summary. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.limited_partners.lps_commitments_aggregates( + lp_id="calpers", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.lps_commitments_aggregates(lp_id, request_options=request_options) + return _response.data + + async def lps_allocations_target( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get target allocation percentages by asset class, geography, and strategy. Returns investment policy guidelines and target portfolio mix. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.limited_partners.lps_allocations_target( + lp_id="calpers", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.lps_allocations_target(lp_id, request_options=request_options) + return _response.data + + async def lps_allocations_actual( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get actual current allocation percentages by asset class, geography, and strategy. Returns real portfolio composition and compare to targets. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.limited_partners.lps_allocations_actual( + lp_id="calpers", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.lps_allocations_actual(lp_id, request_options=request_options) + return _response.data + + async def lps_commitment_preferences( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get commitment preferences including preferred fund sizes, vintage year focus, and investment stage preferences. Useful for GP fundraising targeting. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.limited_partners.lps_commitment_preferences( + lp_id="calpers", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.lps_commitment_preferences(lp_id, request_options=request_options) + return _response.data + + async def lps_service_providers( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get service providers used by the LP including consultants, custodians, and legal advisors. Returns firm names and service types. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.limited_partners.lps_service_providers( + lp_id="calpers", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.lps_service_providers(lp_id, request_options=request_options) + return _response.data + + async def lps_updates( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to LP profile data. Returns history of changes including new commitments, policy changes, and team updates with timestamps. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.limited_partners.lps_updates( + lp_id="calpers", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.lps_updates(lp_id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/limited_partners/raw_client.py b/src/runcaptain/limited_partners/raw_client.py new file mode 100644 index 0000000..696dff5 --- /dev/null +++ b/src/runcaptain/limited_partners/raw_client.py @@ -0,0 +1,1222 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.not_implemented_error import NotImplementedError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawLimitedPartnersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def lps_search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for institutional limited partners including pension funds, endowments, and family offices. Returns matching LP profiles with total commitments and fund relationships. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/limited-partners/search", + method="GET", + params={ + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lps_bio( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive limited partner profile including institution type, total assets under management, investment strategy, and notable fund commitments. This is the primary endpoint for LP overview data. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lps_commitments_detailed( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get detailed fund commitments including specific fund names, commitment amounts, vintage years, and commitment status. Returns complete LP portfolio. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/commitments/detailed", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lps_commitments_aggregates( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get aggregated commitment statistics including total commitments by vintage year, fund type, and geography. Returns high-level allocation summary. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/commitments/aggregates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lps_allocations_target( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get target allocation percentages by asset class, geography, and strategy. Returns investment policy guidelines and target portfolio mix. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/allocations/target", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lps_allocations_actual( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get actual current allocation percentages by asset class, geography, and strategy. Returns real portfolio composition and compare to targets. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/allocations/actual", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lps_commitment_preferences( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get commitment preferences including preferred fund sizes, vintage year focus, and investment stage preferences. Useful for GP fundraising targeting. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/commitment-preferences", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lps_service_providers( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers used by the LP including consultants, custodians, and legal advisors. Returns firm names and service types. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/service-providers", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def lps_updates( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to LP profile data. Returns history of changes including new commitments, policy changes, and team updates with timestamps. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawLimitedPartnersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def lps_search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for institutional limited partners including pension funds, endowments, and family offices. Returns matching LP profiles with total commitments and fund relationships. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/limited-partners/search", + method="GET", + params={ + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lps_bio( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive limited partner profile including institution type, total assets under management, investment strategy, and notable fund commitments. This is the primary endpoint for LP overview data. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lps_commitments_detailed( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get detailed fund commitments including specific fund names, commitment amounts, vintage years, and commitment status. Returns complete LP portfolio. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/commitments/detailed", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lps_commitments_aggregates( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get aggregated commitment statistics including total commitments by vintage year, fund type, and geography. Returns high-level allocation summary. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/commitments/aggregates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lps_allocations_target( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get target allocation percentages by asset class, geography, and strategy. Returns investment policy guidelines and target portfolio mix. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/allocations/target", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lps_allocations_actual( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get actual current allocation percentages by asset class, geography, and strategy. Returns real portfolio composition and compare to targets. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/allocations/actual", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lps_commitment_preferences( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get commitment preferences including preferred fund sizes, vintage year focus, and investment stage preferences. Useful for GP fundraising targeting. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/commitment-preferences", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lps_service_providers( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get service providers used by the LP including consultants, custodians, and legal advisors. Returns firm names and service types. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/service-providers", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def lps_updates( + self, lp_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to LP profile data. Returns history of changes including new commitments, policy changes, and team updates with timestamps. + + Parameters + ---------- + lp_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/limited-partners/{jsonable_encoder(lp_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/patents/__init__.py b/src/runcaptain/patents/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/patents/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/patents/client.py b/src/runcaptain/patents/client.py new file mode 100644 index 0000000..e3bc0f6 --- /dev/null +++ b/src/runcaptain/patents/client.py @@ -0,0 +1,259 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawPatentsClient, RawPatentsClient + + +class PatentsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawPatentsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawPatentsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawPatentsClient + """ + return self._raw_client + + def search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Search for patents by title, inventor, assignee, or classification. Returns matching patents with patent numbers, titles, filing dates, and status. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.patents.search() + """ + _response = self._raw_client.search(limit=limit, request_options=request_options) + return _response.data + + def get_by_id( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get detailed patent information including abstract, claims, inventors, citations, and prosecution history. Returns comprehensive patent profile. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.patents.get_by_id( + id="deal_openai_0", + ) + """ + _response = self._raw_client.get_by_id(id, request_options=request_options) + return _response.data + + def get_file( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Download patent file wrapper or PDF document. Returns patent documentation and prosecution history files. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.patents.get_file( + entity_id="US11234567B2", + ) + """ + _response = self._raw_client.get_file(entity_id, request_options=request_options) + return _response.data + + +class AsyncPatentsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawPatentsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawPatentsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawPatentsClient + """ + return self._raw_client + + async def search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Search for patents by title, inventor, assignee, or classification. Returns matching patents with patent numbers, titles, filing dates, and status. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.patents.search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.search(limit=limit, request_options=request_options) + return _response.data + + async def get_by_id( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get detailed patent information including abstract, claims, inventors, citations, and prosecution history. Returns comprehensive patent profile. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.patents.get_by_id( + id="deal_openai_0", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_by_id(id, request_options=request_options) + return _response.data + + async def get_file( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Download patent file wrapper or PDF document. Returns patent documentation and prosecution history files. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.patents.get_file( + entity_id="US11234567B2", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_file(entity_id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/patents/raw_client.py b/src/runcaptain/patents/raw_client.py new file mode 100644 index 0000000..aea446d --- /dev/null +++ b/src/runcaptain/patents/raw_client.py @@ -0,0 +1,392 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.not_implemented_error import NotImplementedError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawPatentsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for patents by title, inventor, assignee, or classification. Returns matching patents with patent numbers, titles, filing dates, and status. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/patents/search", + method="GET", + params={ + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_by_id( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get detailed patent information including abstract, claims, inventors, citations, and prosecution history. Returns comprehensive patent profile. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/patents/{jsonable_encoder(id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_file( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Download patent file wrapper or PDF document. Returns patent documentation and prosecution history files. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/patents/{jsonable_encoder(entity_id)}/file", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawPatentsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def search( + self, *, limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for patents by title, inventor, assignee, or classification. Returns matching patents with patent numbers, titles, filing dates, and status. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/patents/search", + method="GET", + params={ + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_by_id( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get detailed patent information including abstract, claims, inventors, citations, and prosecution history. Returns comprehensive patent profile. + + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/patents/{jsonable_encoder(id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_file( + self, entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Download patent file wrapper or PDF document. Returns patent documentation and prosecution history files. + + Parameters + ---------- + entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/patents/{jsonable_encoder(entity_id)}/file", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/people/__init__.py b/src/runcaptain/people/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/people/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/people/client.py b/src/runcaptain/people/client.py new file mode 100644 index 0000000..a260062 --- /dev/null +++ b/src/runcaptain/people/client.py @@ -0,0 +1,433 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawPeopleClient, RawPeopleClient + + +class PeopleClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawPeopleClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawPeopleClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawPeopleClient + """ + return self._raw_client + + def search( + self, + *, + title: typing.Optional[str] = None, + location: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for professionals by name, company, title, or location. Returns matching profiles with current position, company, and LinkedIn URL. Use this to find person entity IDs for detailed lookups. + + Parameters + ---------- + title : typing.Optional[str] + Filter by job title + + location : typing.Optional[str] + Filter by location + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.people.search() + """ + _response = self._raw_client.search( + title=title, location=location, limit=limit, request_options=request_options + ) + return _response.data + + def bio( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive person profile including headline, summary, current company, location, and social profiles. This is the primary endpoint for person overview data. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.people.bio( + person_id="ody_pe_019cb8ac-f123-749e-a75e-e5f669g53c05", + ) + """ + _response = self._raw_client.bio(person_id, request_options=request_options) + return _response.data + + def contact( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get contact information including email addresses, phone numbers, and social media profiles. Returns verified contact details for outreach. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.people.contact( + person_id="linkedin.com/in/samaltman", + ) + """ + _response = self._raw_client.contact(person_id, request_options=request_options) + return _response.data + + def education_work( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get complete professional history including work experience and education. Returns job positions with companies, titles, dates, and degree information with schools and majors. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.people.education_work( + person_id="linkedin.com/in/samaltman", + ) + """ + _response = self._raw_client.education_work(person_id, request_options=request_options) + return _response.data + + def updates( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to person profile data. Returns history of career moves, title changes, and profile updates with timestamps. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.people.updates( + person_id="linkedin.com/in/samaltman", + ) + """ + _response = self._raw_client.updates(person_id, request_options=request_options) + return _response.data + + +class AsyncPeopleClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawPeopleClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawPeopleClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawPeopleClient + """ + return self._raw_client + + async def search( + self, + *, + title: typing.Optional[str] = None, + location: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for professionals by name, company, title, or location. Returns matching profiles with current position, company, and LinkedIn URL. Use this to find person entity IDs for detailed lookups. + + Parameters + ---------- + title : typing.Optional[str] + Filter by job title + + location : typing.Optional[str] + Filter by location + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.people.search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.search( + title=title, location=location, limit=limit, request_options=request_options + ) + return _response.data + + async def bio( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive person profile including headline, summary, current company, location, and social profiles. This is the primary endpoint for person overview data. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.people.bio( + person_id="ody_pe_019cb8ac-f123-749e-a75e-e5f669g53c05", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.bio(person_id, request_options=request_options) + return _response.data + + async def contact( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get contact information including email addresses, phone numbers, and social media profiles. Returns verified contact details for outreach. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.people.contact( + person_id="linkedin.com/in/samaltman", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.contact(person_id, request_options=request_options) + return _response.data + + async def education_work( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get complete professional history including work experience and education. Returns job positions with companies, titles, dates, and degree information with schools and majors. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.people.education_work( + person_id="linkedin.com/in/samaltman", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.education_work(person_id, request_options=request_options) + return _response.data + + async def updates( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to person profile data. Returns history of career moves, title changes, and profile updates with timestamps. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.people.updates( + person_id="linkedin.com/in/samaltman", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.updates(person_id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/people/raw_client.py b/src/runcaptain/people/raw_client.py new file mode 100644 index 0000000..81463ec --- /dev/null +++ b/src/runcaptain/people/raw_client.py @@ -0,0 +1,635 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawPeopleClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def search( + self, + *, + title: typing.Optional[str] = None, + location: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for professionals by name, company, title, or location. Returns matching profiles with current position, company, and LinkedIn URL. Use this to find person entity IDs for detailed lookups. + + Parameters + ---------- + title : typing.Optional[str] + Filter by job title + + location : typing.Optional[str] + Filter by location + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/people/search", + method="GET", + params={ + "title": title, + "location": location, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def bio( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive person profile including headline, summary, current company, location, and social profiles. This is the primary endpoint for person overview data. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/people/{jsonable_encoder(person_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def contact( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get contact information including email addresses, phone numbers, and social media profiles. Returns verified contact details for outreach. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/people/{jsonable_encoder(person_id)}/contact", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def education_work( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get complete professional history including work experience and education. Returns job positions with companies, titles, dates, and degree information with schools and majors. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/people/{jsonable_encoder(person_id)}/education-work", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def updates( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to person profile data. Returns history of career moves, title changes, and profile updates with timestamps. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/people/{jsonable_encoder(person_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawPeopleClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def search( + self, + *, + title: typing.Optional[str] = None, + location: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for professionals by name, company, title, or location. Returns matching profiles with current position, company, and LinkedIn URL. Use this to find person entity IDs for detailed lookups. + + Parameters + ---------- + title : typing.Optional[str] + Filter by job title + + location : typing.Optional[str] + Filter by location + + limit : typing.Optional[int] + Maximum results + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/people/search", + method="GET", + params={ + "title": title, + "location": location, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def bio( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive person profile including headline, summary, current company, location, and social profiles. This is the primary endpoint for person overview data. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/people/{jsonable_encoder(person_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def contact( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get contact information including email addresses, phone numbers, and social media profiles. Returns verified contact details for outreach. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/people/{jsonable_encoder(person_id)}/contact", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def education_work( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get complete professional history including work experience and education. Returns job positions with companies, titles, dates, and degree information with schools and majors. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/people/{jsonable_encoder(person_id)}/education-work", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def updates( + self, person_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to person profile data. Returns history of career moves, title changes, and profile updates with timestamps. + + Parameters + ---------- + person_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/people/{jsonable_encoder(person_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/query/client.py b/src/runcaptain/query/client.py index d0d0ed9..d4bf2ac 100644 --- a/src/runcaptain/query/client.py +++ b/src/runcaptain/query/client.py @@ -5,6 +5,7 @@ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.request_options import RequestOptions from ..types.query_response_v2 import QueryResponseV2 +from ..types.query_stream_event import QueryStreamEvent from .raw_client import AsyncRawQueryClient, RawQueryClient # this is used as the default value for optional parameters @@ -26,13 +27,122 @@ def with_raw_response(self) -> RawQueryClient: """ return self._raw_client + def collection_v2stream( + self, + collection_name: str, + *, + query: str, + inference: typing.Optional[bool] = OMIT, + top_k: typing.Optional[int] = OMIT, + rerank: typing.Optional[bool] = OMIT, + metadata_filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + custom_prompt: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[QueryStreamEvent]: + """ + Execute a natural language query against a collection. + + When `inference=true`, returns an AI-generated response with relevant documents. + When `inference=false`, returns raw search results with content and metadata. + + ## Streaming (SSE) + + When `stream: true` and `inference: true`, the response is a Server-Sent Events stream. Every `data:` field is a JSON object with a `type` discriminator. + + ### SSE Event Types + + | `type` value | Schema | Description | + |---|---|---| + | `text.delta` | `QueryStreamTextEvent` | Incremental text chunk of the AI response. | + | `tool.start` | `QueryStreamToolStartEvent` | The agent is performing a knowledge-base search. | + | `tool.end` | `QueryStreamToolEndEvent` | A tool call completed. `tool_call_id` correlates with the preceding `tool.start`. | + | `stream_complete` | `QueryStreamCompleteEvent` | Stream finished successfully. Close the connection. | + | `stream_error` | `QueryStreamErrorEvent` | An error occurred. Close the connection. | + + ### Example SSE Stream + + ``` + data: {"type":"tool.start","seq":1,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","args":{"query":"revenue projections Q4"}} + + data: {"type":"tool.end","seq":2,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","ok":true,"result_summary":{"resultCount":12}} + + data: {"type":"text.delta","seq":3,"run_id":"run_abc","data":"Based on the documents"} + data: {"type":"text.delta","seq":4,"run_id":"run_abc","data":" provided, the revenue"} + data: {"type":"text.delta","seq":5,"run_id":"run_abc","data":" projections for Q4 show"} + data: {"type":"text.delta","seq":6,"run_id":"run_abc","data":" a 15% increase over Q3."} + + data: {"type":"stream_complete","metadata":{"totalResults":12,"totalSearches":1},"stats":{"totalTokens":150}} + ``` + + ### Notes + + - The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. + - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. + - Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses. + + Parameters + ---------- + collection_name : str + + query : str + The natural language query to search for + + inference : typing.Optional[bool] + Enable LLM-generated answers based on the relevant sections retrieved. When false, returns raw search results. + + top_k : typing.Optional[int] + Number of results to return. Only valid when inference=false. Not supported when inference=true (the agent controls its own search strategy). + + rerank : typing.Optional[bool] + Enable Voyage AI rerank-2.5 reranking for improved relevance ordering. Adds ~100-300ms latency. + + metadata_filter : typing.Optional[typing.Dict[str, typing.Any]] + Filter expression for vector search. Supports: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $and, $or + + custom_prompt : typing.Optional[str] + Custom system prompt to override the default RAG prompt when inference=true. Allows customizing how the LLM processes and responds to the query with the retrieved context. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Yields + ------ + typing.Iterator[QueryStreamEvent] + + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + response = client.query.collection_v2stream( + collection_name="collection_name", + query="query", + ) + for chunk in response: + yield chunk + """ + with self._raw_client.collection_v2stream( + collection_name, + query=query, + inference=inference, + top_k=top_k, + rerank=rerank, + metadata_filter=metadata_filter, + custom_prompt=custom_prompt, + request_options=request_options, + ) as r: + yield from r.data + def collection_v2( self, collection_name: str, *, query: str, inference: typing.Optional[bool] = OMIT, - stream: typing.Optional[bool] = OMIT, top_k: typing.Optional[int] = OMIT, rerank: typing.Optional[bool] = OMIT, metadata_filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, @@ -77,7 +187,7 @@ def collection_v2( ### Notes - The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. - - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. + - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. - Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses. Parameters @@ -90,9 +200,6 @@ def collection_v2( inference : typing.Optional[bool] Enable LLM-generated answers based on the relevant sections retrieved. When false, returns raw search results. - stream : typing.Optional[bool] - Enable real-time streaming of the response - top_k : typing.Optional[int] Number of results to return. Only valid when inference=false. Not supported when inference=true (the agent controls its own search strategy). @@ -111,7 +218,7 @@ def collection_v2( Returns ------- QueryResponseV2 - Successful Response — returns JSON when `stream: false`, or SSE event stream when `stream: true`. + Examples -------- @@ -125,7 +232,6 @@ def collection_v2( collection_name="my_documents", query="What are the key terms in the contract?", inference=False, - stream=False, rerank=True, top_k=10, ) @@ -134,7 +240,6 @@ def collection_v2( collection_name, query=query, inference=inference, - stream=stream, top_k=top_k, rerank=rerank, metadata_filter=metadata_filter, @@ -159,13 +264,131 @@ def with_raw_response(self) -> AsyncRawQueryClient: """ return self._raw_client + async def collection_v2stream( + self, + collection_name: str, + *, + query: str, + inference: typing.Optional[bool] = OMIT, + top_k: typing.Optional[int] = OMIT, + rerank: typing.Optional[bool] = OMIT, + metadata_filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + custom_prompt: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[QueryStreamEvent]: + """ + Execute a natural language query against a collection. + + When `inference=true`, returns an AI-generated response with relevant documents. + When `inference=false`, returns raw search results with content and metadata. + + ## Streaming (SSE) + + When `stream: true` and `inference: true`, the response is a Server-Sent Events stream. Every `data:` field is a JSON object with a `type` discriminator. + + ### SSE Event Types + + | `type` value | Schema | Description | + |---|---|---| + | `text.delta` | `QueryStreamTextEvent` | Incremental text chunk of the AI response. | + | `tool.start` | `QueryStreamToolStartEvent` | The agent is performing a knowledge-base search. | + | `tool.end` | `QueryStreamToolEndEvent` | A tool call completed. `tool_call_id` correlates with the preceding `tool.start`. | + | `stream_complete` | `QueryStreamCompleteEvent` | Stream finished successfully. Close the connection. | + | `stream_error` | `QueryStreamErrorEvent` | An error occurred. Close the connection. | + + ### Example SSE Stream + + ``` + data: {"type":"tool.start","seq":1,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","args":{"query":"revenue projections Q4"}} + + data: {"type":"tool.end","seq":2,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","ok":true,"result_summary":{"resultCount":12}} + + data: {"type":"text.delta","seq":3,"run_id":"run_abc","data":"Based on the documents"} + data: {"type":"text.delta","seq":4,"run_id":"run_abc","data":" provided, the revenue"} + data: {"type":"text.delta","seq":5,"run_id":"run_abc","data":" projections for Q4 show"} + data: {"type":"text.delta","seq":6,"run_id":"run_abc","data":" a 15% increase over Q3."} + + data: {"type":"stream_complete","metadata":{"totalResults":12,"totalSearches":1},"stats":{"totalTokens":150}} + ``` + + ### Notes + + - The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. + - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. + - Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses. + + Parameters + ---------- + collection_name : str + + query : str + The natural language query to search for + + inference : typing.Optional[bool] + Enable LLM-generated answers based on the relevant sections retrieved. When false, returns raw search results. + + top_k : typing.Optional[int] + Number of results to return. Only valid when inference=false. Not supported when inference=true (the agent controls its own search strategy). + + rerank : typing.Optional[bool] + Enable Voyage AI rerank-2.5 reranking for improved relevance ordering. Adds ~100-300ms latency. + + metadata_filter : typing.Optional[typing.Dict[str, typing.Any]] + Filter expression for vector search. Supports: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $and, $or + + custom_prompt : typing.Optional[str] + Custom system prompt to override the default RAG prompt when inference=true. Allows customizing how the LLM processes and responds to the query with the retrieved context. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Yields + ------ + typing.AsyncIterator[QueryStreamEvent] + + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + response = await client.query.collection_v2stream( + collection_name="collection_name", + query="query", + ) + async for chunk in response: + yield chunk + + + asyncio.run(main()) + """ + async with self._raw_client.collection_v2stream( + collection_name, + query=query, + inference=inference, + top_k=top_k, + rerank=rerank, + metadata_filter=metadata_filter, + custom_prompt=custom_prompt, + request_options=request_options, + ) as r: + async for _chunk in r.data: + yield _chunk + async def collection_v2( self, collection_name: str, *, query: str, inference: typing.Optional[bool] = OMIT, - stream: typing.Optional[bool] = OMIT, top_k: typing.Optional[int] = OMIT, rerank: typing.Optional[bool] = OMIT, metadata_filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, @@ -210,7 +433,7 @@ async def collection_v2( ### Notes - The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. - - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. + - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. - Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses. Parameters @@ -223,9 +446,6 @@ async def collection_v2( inference : typing.Optional[bool] Enable LLM-generated answers based on the relevant sections retrieved. When false, returns raw search results. - stream : typing.Optional[bool] - Enable real-time streaming of the response - top_k : typing.Optional[int] Number of results to return. Only valid when inference=false. Not supported when inference=true (the agent controls its own search strategy). @@ -244,7 +464,7 @@ async def collection_v2( Returns ------- QueryResponseV2 - Successful Response — returns JSON when `stream: false`, or SSE event stream when `stream: true`. + Examples -------- @@ -263,7 +483,6 @@ async def main() -> None: collection_name="my_documents", query="What are the key terms in the contract?", inference=False, - stream=False, rerank=True, top_k=10, ) @@ -275,7 +494,6 @@ async def main() -> None: collection_name, query=query, inference=inference, - stream=stream, top_k=top_k, rerank=rerank, metadata_filter=metadata_filter, diff --git a/src/runcaptain/query/raw_client.py b/src/runcaptain/query/raw_client.py index d948a4d..22a7d87 100644 --- a/src/runcaptain/query/raw_client.py +++ b/src/runcaptain/query/raw_client.py @@ -1,15 +1,19 @@ # This file was auto-generated by Fern from our API Definition. +import contextlib import typing from json.decoder import JSONDecodeError +from logging import error, warning from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.http_sse._api import EventSource from ..core.jsonable_encoder import jsonable_encoder -from ..core.pydantic_utilities import parse_obj_as +from ..core.pydantic_utilities import parse_obj_as, parse_sse_obj from ..core.request_options import RequestOptions from ..types.query_response_v2 import QueryResponseV2 +from ..types.query_stream_event import QueryStreamEvent # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -19,13 +23,155 @@ class RawQueryClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper + @contextlib.contextmanager + def collection_v2stream( + self, + collection_name: str, + *, + query: str, + inference: typing.Optional[bool] = OMIT, + top_k: typing.Optional[int] = OMIT, + rerank: typing.Optional[bool] = OMIT, + metadata_filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + custom_prompt: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[HttpResponse[typing.Iterator[QueryStreamEvent]]]: + """ + Execute a natural language query against a collection. + + When `inference=true`, returns an AI-generated response with relevant documents. + When `inference=false`, returns raw search results with content and metadata. + + ## Streaming (SSE) + + When `stream: true` and `inference: true`, the response is a Server-Sent Events stream. Every `data:` field is a JSON object with a `type` discriminator. + + ### SSE Event Types + + | `type` value | Schema | Description | + |---|---|---| + | `text.delta` | `QueryStreamTextEvent` | Incremental text chunk of the AI response. | + | `tool.start` | `QueryStreamToolStartEvent` | The agent is performing a knowledge-base search. | + | `tool.end` | `QueryStreamToolEndEvent` | A tool call completed. `tool_call_id` correlates with the preceding `tool.start`. | + | `stream_complete` | `QueryStreamCompleteEvent` | Stream finished successfully. Close the connection. | + | `stream_error` | `QueryStreamErrorEvent` | An error occurred. Close the connection. | + + ### Example SSE Stream + + ``` + data: {"type":"tool.start","seq":1,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","args":{"query":"revenue projections Q4"}} + + data: {"type":"tool.end","seq":2,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","ok":true,"result_summary":{"resultCount":12}} + + data: {"type":"text.delta","seq":3,"run_id":"run_abc","data":"Based on the documents"} + data: {"type":"text.delta","seq":4,"run_id":"run_abc","data":" provided, the revenue"} + data: {"type":"text.delta","seq":5,"run_id":"run_abc","data":" projections for Q4 show"} + data: {"type":"text.delta","seq":6,"run_id":"run_abc","data":" a 15% increase over Q3."} + + data: {"type":"stream_complete","metadata":{"totalResults":12,"totalSearches":1},"stats":{"totalTokens":150}} + ``` + + ### Notes + + - The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. + - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. + - Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses. + + Parameters + ---------- + collection_name : str + + query : str + The natural language query to search for + + inference : typing.Optional[bool] + Enable LLM-generated answers based on the relevant sections retrieved. When false, returns raw search results. + + top_k : typing.Optional[int] + Number of results to return. Only valid when inference=false. Not supported when inference=true (the agent controls its own search strategy). + + rerank : typing.Optional[bool] + Enable Voyage AI rerank-2.5 reranking for improved relevance ordering. Adds ~100-300ms latency. + + metadata_filter : typing.Optional[typing.Dict[str, typing.Any]] + Filter expression for vector search. Supports: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $and, $or + + custom_prompt : typing.Optional[str] + Custom system prompt to override the default RAG prompt when inference=true. Allows customizing how the LLM processes and responds to the query with the retrieved context. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Yields + ------ + typing.Iterator[HttpResponse[typing.Iterator[QueryStreamEvent]]] + + """ + with self._client_wrapper.httpx_client.stream( + f"v2/collections/{jsonable_encoder(collection_name)}/query", + method="POST", + json={ + "query": query, + "inference": inference, + "top_k": top_k, + "rerank": rerank, + "metadata_filter": metadata_filter, + "custom_prompt": custom_prompt, + "stream": True, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) as _response: + + def _stream() -> HttpResponse[typing.Iterator[QueryStreamEvent]]: + try: + if 200 <= _response.status_code < 300: + + def _iter(): + _event_source = EventSource(_response) + for _sse in _event_source.iter_sse(): + if _sse.data == None: + return + try: + yield typing.cast( + QueryStreamEvent, + parse_sse_obj( + sse=_sse, + type_=QueryStreamEvent, # type: ignore + ), + ) + except JSONDecodeError as e: + warning(f"Skipping SSE event with invalid JSON: {e}, sse: {_sse!r}") + except (TypeError, ValueError, KeyError, AttributeError) as e: + warning( + f"Skipping SSE event due to model construction error: {type(e).__name__}: {e}, sse: {_sse!r}" + ) + except Exception as e: + error( + f"Unexpected error processing SSE event: {type(e).__name__}: {e}, sse: {_sse!r}" + ) + return + + return HttpResponse(response=_response, data=_iter()) + _response.read() + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() + def collection_v2( self, collection_name: str, *, query: str, inference: typing.Optional[bool] = OMIT, - stream: typing.Optional[bool] = OMIT, top_k: typing.Optional[int] = OMIT, rerank: typing.Optional[bool] = OMIT, metadata_filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, @@ -70,7 +216,7 @@ def collection_v2( ### Notes - The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. - - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. + - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. - Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses. Parameters @@ -83,9 +229,6 @@ def collection_v2( inference : typing.Optional[bool] Enable LLM-generated answers based on the relevant sections retrieved. When false, returns raw search results. - stream : typing.Optional[bool] - Enable real-time streaming of the response - top_k : typing.Optional[int] Number of results to return. Only valid when inference=false. Not supported when inference=true (the agent controls its own search strategy). @@ -104,7 +247,7 @@ def collection_v2( Returns ------- HttpResponse[QueryResponseV2] - Successful Response — returns JSON when `stream: false`, or SSE event stream when `stream: true`. + """ _response = self._client_wrapper.httpx_client.request( f"v2/collections/{jsonable_encoder(collection_name)}/query", @@ -112,11 +255,11 @@ def collection_v2( json={ "query": query, "inference": inference, - "stream": stream, "top_k": top_k, "rerank": rerank, "metadata_filter": metadata_filter, "custom_prompt": custom_prompt, + "stream": False, }, headers={ "content-type": "application/json", @@ -144,13 +287,155 @@ class AsyncRawQueryClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper + @contextlib.asynccontextmanager + async def collection_v2stream( + self, + collection_name: str, + *, + query: str, + inference: typing.Optional[bool] = OMIT, + top_k: typing.Optional[int] = OMIT, + rerank: typing.Optional[bool] = OMIT, + metadata_filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + custom_prompt: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[QueryStreamEvent]]]: + """ + Execute a natural language query against a collection. + + When `inference=true`, returns an AI-generated response with relevant documents. + When `inference=false`, returns raw search results with content and metadata. + + ## Streaming (SSE) + + When `stream: true` and `inference: true`, the response is a Server-Sent Events stream. Every `data:` field is a JSON object with a `type` discriminator. + + ### SSE Event Types + + | `type` value | Schema | Description | + |---|---|---| + | `text.delta` | `QueryStreamTextEvent` | Incremental text chunk of the AI response. | + | `tool.start` | `QueryStreamToolStartEvent` | The agent is performing a knowledge-base search. | + | `tool.end` | `QueryStreamToolEndEvent` | A tool call completed. `tool_call_id` correlates with the preceding `tool.start`. | + | `stream_complete` | `QueryStreamCompleteEvent` | Stream finished successfully. Close the connection. | + | `stream_error` | `QueryStreamErrorEvent` | An error occurred. Close the connection. | + + ### Example SSE Stream + + ``` + data: {"type":"tool.start","seq":1,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","args":{"query":"revenue projections Q4"}} + + data: {"type":"tool.end","seq":2,"run_id":"run_abc","tool_call_id":"tc_1","name":"searchKnowledgeBase","ok":true,"result_summary":{"resultCount":12}} + + data: {"type":"text.delta","seq":3,"run_id":"run_abc","data":"Based on the documents"} + data: {"type":"text.delta","seq":4,"run_id":"run_abc","data":" provided, the revenue"} + data: {"type":"text.delta","seq":5,"run_id":"run_abc","data":" projections for Q4 show"} + data: {"type":"text.delta","seq":6,"run_id":"run_abc","data":" a 15% increase over Q3."} + + data: {"type":"stream_complete","metadata":{"totalResults":12,"totalSearches":1},"stats":{"totalTokens":150}} + ``` + + ### Notes + + - The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. + - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. + - Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses. + + Parameters + ---------- + collection_name : str + + query : str + The natural language query to search for + + inference : typing.Optional[bool] + Enable LLM-generated answers based on the relevant sections retrieved. When false, returns raw search results. + + top_k : typing.Optional[int] + Number of results to return. Only valid when inference=false. Not supported when inference=true (the agent controls its own search strategy). + + rerank : typing.Optional[bool] + Enable Voyage AI rerank-2.5 reranking for improved relevance ordering. Adds ~100-300ms latency. + + metadata_filter : typing.Optional[typing.Dict[str, typing.Any]] + Filter expression for vector search. Supports: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $and, $or + + custom_prompt : typing.Optional[str] + Custom system prompt to override the default RAG prompt when inference=true. Allows customizing how the LLM processes and responds to the query with the retrieved context. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Yields + ------ + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[QueryStreamEvent]]] + + """ + async with self._client_wrapper.httpx_client.stream( + f"v2/collections/{jsonable_encoder(collection_name)}/query", + method="POST", + json={ + "query": query, + "inference": inference, + "top_k": top_k, + "rerank": rerank, + "metadata_filter": metadata_filter, + "custom_prompt": custom_prompt, + "stream": True, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) as _response: + + async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[QueryStreamEvent]]: + try: + if 200 <= _response.status_code < 300: + + async def _iter(): + _event_source = EventSource(_response) + async for _sse in _event_source.aiter_sse(): + if _sse.data == None: + return + try: + yield typing.cast( + QueryStreamEvent, + parse_sse_obj( + sse=_sse, + type_=QueryStreamEvent, # type: ignore + ), + ) + except JSONDecodeError as e: + warning(f"Skipping SSE event with invalid JSON: {e}, sse: {_sse!r}") + except (TypeError, ValueError, KeyError, AttributeError) as e: + warning( + f"Skipping SSE event due to model construction error: {type(e).__name__}: {e}, sse: {_sse!r}" + ) + except Exception as e: + error( + f"Unexpected error processing SSE event: {type(e).__name__}: {e}, sse: {_sse!r}" + ) + return + + return AsyncHttpResponse(response=_response, data=_iter()) + await _response.aread() + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() + async def collection_v2( self, collection_name: str, *, query: str, inference: typing.Optional[bool] = OMIT, - stream: typing.Optional[bool] = OMIT, top_k: typing.Optional[int] = OMIT, rerank: typing.Optional[bool] = OMIT, metadata_filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, @@ -195,7 +480,7 @@ async def collection_v2( ### Notes - The agent may perform multiple searches per query. Each search produces a `tool.start` / `tool.end` pair. - - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. + - Text chunks are interleaved between tool events — text arrives after the agent has gathered results from a search. - Connect with `Accept: text/event-stream` and set a generous timeout (120s+) for long responses. Parameters @@ -208,9 +493,6 @@ async def collection_v2( inference : typing.Optional[bool] Enable LLM-generated answers based on the relevant sections retrieved. When false, returns raw search results. - stream : typing.Optional[bool] - Enable real-time streaming of the response - top_k : typing.Optional[int] Number of results to return. Only valid when inference=false. Not supported when inference=true (the agent controls its own search strategy). @@ -229,7 +511,7 @@ async def collection_v2( Returns ------- AsyncHttpResponse[QueryResponseV2] - Successful Response — returns JSON when `stream: false`, or SSE event stream when `stream: true`. + """ _response = await self._client_wrapper.httpx_client.request( f"v2/collections/{jsonable_encoder(collection_name)}/query", @@ -237,11 +519,11 @@ async def collection_v2( json={ "query": query, "inference": inference, - "stream": stream, "top_k": top_k, "rerank": rerank, "metadata_filter": metadata_filter, "custom_prompt": custom_prompt, + "stream": False, }, headers={ "content-type": "application/json", diff --git a/src/runcaptain/service_providers/__init__.py b/src/runcaptain/service_providers/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/runcaptain/service_providers/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/runcaptain/service_providers/client.py b/src/runcaptain/service_providers/client.py new file mode 100644 index 0000000..1801466 --- /dev/null +++ b/src/runcaptain/service_providers/client.py @@ -0,0 +1,645 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawServiceProvidersClient, RawServiceProvidersClient + + +class ServiceProvidersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawServiceProvidersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawServiceProvidersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawServiceProvidersClient + """ + return self._raw_client + + def search( + self, + *, + limit: typing.Optional[int] = None, + provider_type: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for service providers including law firms, accounting firms, investment banks, and consultants. Returns matching provider profiles with specializations and notable clients. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + provider_type : typing.Optional[str] + Provider type filter + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.service_providers.search() + """ + _response = self._raw_client.search(limit=limit, provider_type=provider_type, request_options=request_options) + return _response.data + + def bio( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive service provider profile including firm description, practice areas, office locations, and notable work. This is the primary endpoint for provider overview data. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.service_providers.bio( + provider_id="wilson-sonsini", + ) + """ + _response = self._raw_client.bio(provider_id, request_options=request_options) + return _response.data + + def companies( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get companies that have engaged this service provider. Returns client list with engagement types and sectors served. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.service_providers.companies( + provider_id="wilson-sonsini", + ) + """ + _response = self._raw_client.companies(provider_id, request_options=request_options) + return _response.data + + def deals( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get deals where this provider was involved as advisor, counsel, or banker. Returns transaction history with roles and deal values. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.service_providers.deals( + provider_id="wilson-sonsini", + ) + """ + _response = self._raw_client.deals(provider_id, request_options=request_options) + return _response.data + + def investors( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get investors that have engaged this service provider. Returns investor clients with engagement types and fund formation work. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.service_providers.investors( + provider_id="wilson-sonsini", + ) + """ + _response = self._raw_client.investors(provider_id, request_options=request_options) + return _response.data + + def funds( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get funds that have engaged this service provider. Returns fund formation and compliance work with engagement details. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.service_providers.funds( + provider_id="wilson-sonsini", + ) + """ + _response = self._raw_client.funds(provider_id, request_options=request_options) + return _response.data + + def limited_partners( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get limited partners that have engaged this service provider. Returns LP clients with service types and relationship details. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.service_providers.limited_partners( + provider_id="wilson-sonsini", + ) + """ + _response = self._raw_client.limited_partners(provider_id, request_options=request_options) + return _response.data + + def updates( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to service provider profile data. Returns history of changes including new engagements, office openings, and team changes with timestamps. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + from runcaptain import Captain + + client = Captain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + client.service_providers.updates( + provider_id="wilson-sonsini", + ) + """ + _response = self._raw_client.updates(provider_id, request_options=request_options) + return _response.data + + +class AsyncServiceProvidersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawServiceProvidersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawServiceProvidersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawServiceProvidersClient + """ + return self._raw_client + + async def search( + self, + *, + limit: typing.Optional[int] = None, + provider_type: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Any]: + """ + Search for service providers including law firms, accounting firms, investment banks, and consultants. Returns matching provider profiles with specializations and notable clients. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + provider_type : typing.Optional[str] + Provider type filter + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.service_providers.search() + + + asyncio.run(main()) + """ + _response = await self._raw_client.search( + limit=limit, provider_type=provider_type, request_options=request_options + ) + return _response.data + + async def bio( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get comprehensive service provider profile including firm description, practice areas, office locations, and notable work. This is the primary endpoint for provider overview data. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.service_providers.bio( + provider_id="wilson-sonsini", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.bio(provider_id, request_options=request_options) + return _response.data + + async def companies( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get companies that have engaged this service provider. Returns client list with engagement types and sectors served. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.service_providers.companies( + provider_id="wilson-sonsini", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.companies(provider_id, request_options=request_options) + return _response.data + + async def deals( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get deals where this provider was involved as advisor, counsel, or banker. Returns transaction history with roles and deal values. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.service_providers.deals( + provider_id="wilson-sonsini", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.deals(provider_id, request_options=request_options) + return _response.data + + async def investors( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get investors that have engaged this service provider. Returns investor clients with engagement types and fund formation work. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.service_providers.investors( + provider_id="wilson-sonsini", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.investors(provider_id, request_options=request_options) + return _response.data + + async def funds( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get funds that have engaged this service provider. Returns fund formation and compliance work with engagement details. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.service_providers.funds( + provider_id="wilson-sonsini", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.funds(provider_id, request_options=request_options) + return _response.data + + async def limited_partners( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get limited partners that have engaged this service provider. Returns LP clients with service types and relationship details. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.service_providers.limited_partners( + provider_id="wilson-sonsini", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.limited_partners(provider_id, request_options=request_options) + return _response.data + + async def updates( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, typing.Any]: + """ + Get changelog of updates to service provider profile data. Returns history of changes including new engagements, office openings, and team changes with timestamps. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Any] + Successful response + + Examples + -------- + import asyncio + + from runcaptain import AsyncCaptain + + client = AsyncCaptain( + organization_id="YOUR_ORGANIZATION_ID", + key="YOUR_KEY", + ) + + + async def main() -> None: + await client.service_providers.updates( + provider_id="wilson-sonsini", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.updates(provider_id, request_options=request_options) + return _response.data diff --git a/src/runcaptain/service_providers/raw_client.py b/src/runcaptain/service_providers/raw_client.py new file mode 100644 index 0000000..8d5f208 --- /dev/null +++ b/src/runcaptain/service_providers/raw_client.py @@ -0,0 +1,1096 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.not_found_error import NotFoundError +from ..errors.not_implemented_error import NotImplementedError +from ..errors.unauthorized_error import UnauthorizedError + + +class RawServiceProvidersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def search( + self, + *, + limit: typing.Optional[int] = None, + provider_type: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for service providers including law firms, accounting firms, investment banks, and consultants. Returns matching provider profiles with specializations and notable clients. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + provider_type : typing.Optional[str] + Provider type filter + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/service-providers/search", + method="GET", + params={ + "limit": limit, + "provider_type": provider_type, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def bio( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive service provider profile including firm description, practice areas, office locations, and notable work. This is the primary endpoint for provider overview data. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def companies( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get companies that have engaged this service provider. Returns client list with engagement types and sectors served. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/companies", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def deals( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get deals where this provider was involved as advisor, counsel, or banker. Returns transaction history with roles and deal values. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/deals", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def investors( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get investors that have engaged this service provider. Returns investor clients with engagement types and fund formation work. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/investors", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def funds( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get funds that have engaged this service provider. Returns fund formation and compliance work with engagement details. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/funds", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def limited_partners( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get limited partners that have engaged this service provider. Returns LP clients with service types and relationship details. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/limited-partners", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def updates( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to service provider profile data. Returns history of changes including new engagements, office openings, and team changes with timestamps. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawServiceProvidersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def search( + self, + *, + limit: typing.Optional[int] = None, + provider_type: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Search for service providers including law firms, accounting firms, investment banks, and consultants. Returns matching provider profiles with specializations and notable clients. + + Parameters + ---------- + limit : typing.Optional[int] + Maximum results + + provider_type : typing.Optional[str] + Provider type filter + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + "v2/datasets/odyssey/service-providers/search", + method="GET", + params={ + "limit": limit, + "provider_type": provider_type, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def bio( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get comprehensive service provider profile including firm description, practice areas, office locations, and notable work. This is the primary endpoint for provider overview data. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/bio", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def companies( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get companies that have engaged this service provider. Returns client list with engagement types and sectors served. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/companies", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def deals( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get deals where this provider was involved as advisor, counsel, or banker. Returns transaction history with roles and deal values. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/deals", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def investors( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get investors that have engaged this service provider. Returns investor clients with engagement types and fund formation work. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/investors", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def funds( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get funds that have engaged this service provider. Returns fund formation and compliance work with engagement details. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/funds", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def limited_partners( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get limited partners that have engaged this service provider. Returns LP clients with service types and relationship details. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/limited-partners", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 501: + raise NotImplementedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def updates( + self, provider_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, typing.Any]]: + """ + Get changelog of updates to service provider profile data. Returns history of changes including new engagements, office openings, and team changes with timestamps. + + Parameters + ---------- + provider_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Any]] + Successful response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v2/datasets/odyssey/service-providers/{jsonable_encoder(provider_id)}/updates", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Any], + parse_obj_as( + type_=typing.Dict[str, typing.Any], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/runcaptain/types/__init__.py b/src/runcaptain/types/__init__.py index 8058902..467be36 100644 --- a/src/runcaptain/types/__init__.py +++ b/src/runcaptain/types/__init__.py @@ -31,9 +31,9 @@ from .job_progress import JobProgress from .job_progress_current_stage import JobProgressCurrentStage from .job_result import JobResult + from .job_status import JobStatus from .job_status_response_v2 import JobStatusResponseV2 from .job_status_response_v2job_type import JobStatusResponseV2JobType - from .job_status_response_v2status import JobStatusResponseV2Status from .query_response_v2 import QueryResponseV2 from .query_stream_complete_event import QueryStreamCompleteEvent from .query_stream_error_event import QueryStreamErrorEvent @@ -80,9 +80,9 @@ "JobProgress": ".job_progress", "JobProgressCurrentStage": ".job_progress_current_stage", "JobResult": ".job_result", + "JobStatus": ".job_status", "JobStatusResponseV2": ".job_status_response_v2", "JobStatusResponseV2JobType": ".job_status_response_v2job_type", - "JobStatusResponseV2Status": ".job_status_response_v2status", "QueryResponseV2": ".query_response_v2", "QueryStreamCompleteEvent": ".query_stream_complete_event", "QueryStreamErrorEvent": ".query_stream_error_event", @@ -151,9 +151,9 @@ def __dir__(): "JobProgress", "JobProgressCurrentStage", "JobResult", + "JobStatus", "JobStatusResponseV2", "JobStatusResponseV2JobType", - "JobStatusResponseV2Status", "QueryResponseV2", "QueryStreamCompleteEvent", "QueryStreamErrorEvent", diff --git a/src/runcaptain/types/collection_response_v2.py b/src/runcaptain/types/collection_response_v2.py index c14fd7c..0a0d4a3 100644 --- a/src/runcaptain/types/collection_response_v2.py +++ b/src/runcaptain/types/collection_response_v2.py @@ -8,9 +8,9 @@ class CollectionResponseV2(UniversalBaseModel): collection_name: str - collection_id: str - status: str - message: str + collection_id: typing.Optional[str] = None + status: typing.Optional[str] = None + message: typing.Optional[str] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/runcaptain/types/job_status.py b/src/runcaptain/types/job_status.py new file mode 100644 index 0000000..0e56955 --- /dev/null +++ b/src/runcaptain/types/job_status.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +JobStatus = typing.Union[ + typing.Literal["pending", "running", "completed", "completed_with_failures", "failed", "cancelled"], typing.Any +] diff --git a/src/runcaptain/types/job_status_response_v2.py b/src/runcaptain/types/job_status_response_v2.py index 23077e1..3e5f759 100644 --- a/src/runcaptain/types/job_status_response_v2.py +++ b/src/runcaptain/types/job_status_response_v2.py @@ -10,8 +10,8 @@ from .job_billing import JobBilling from .job_progress import JobProgress from .job_result import JobResult +from .job_status import JobStatus from .job_status_response_v2job_type import JobStatusResponseV2JobType -from .job_status_response_v2status import JobStatusResponseV2Status class JobStatusResponseV2(UniversalBaseModel): @@ -34,7 +34,7 @@ class JobStatusResponseV2(UniversalBaseModel): Type of indexing job """ - status: JobStatusResponseV2Status = pydantic.Field() + status: JobStatus = pydantic.Field() """ Current job status """ @@ -66,7 +66,7 @@ class JobStatusResponseV2(UniversalBaseModel): billing: typing.Optional[JobBilling] = pydantic.Field(default=None) """ - Billing details including cost, credits used, and remaining balance. Only present when status is 'completed'. + Billing details including cost, credits used, and remaining balance. Present when status is 'completed' or 'completed_with_failures'. """ error_code: typing.Optional[str] = pydantic.Field(default=None) diff --git a/src/runcaptain/types/job_status_response_v2status.py b/src/runcaptain/types/job_status_response_v2status.py deleted file mode 100644 index f5f483b..0000000 --- a/src/runcaptain/types/job_status_response_v2status.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -JobStatusResponseV2Status = typing.Union[ - typing.Literal["pending", "running", "completed", "failed", "cancelled"], typing.Any -]