# List categories - Categories API Source: https://docs.sacra.com/api-reference/categories/list-categories openapi.json GET /api/v1/categories/ Returns categories for a given company, or a single category by slug. **Lookup modes:** - By `slug` — returns the single matching category - By `company_domain` or `company_id` — returns all categories for that company At least one of `company_domain`, `company_id`, or `slug` is required. # List items in a category - Categories API Source: https://docs.sacra.com/api-reference/categories/list-items-in-a-category openapi.json GET /api/v1/categories/{category_slug}/items/ Returns companies and documents belonging to a category, sorted by publication date. Results are a unified list of **companies** and **documents**, each identified by a `type` field. Use `limit` and `offset` for pagination. The `meta` object varies by item type. For companies it includes `domain` and `logo`. For documents it includes `preview_image` and `document_type`. # Get company detail - Companies API Source: https://docs.sacra.com/api-reference/companies/get-a-company-detail openapi.json GET /api/v1/companies/{company_slug}/ Retrieve a company's complete profile, research, financials, and related data by domain, ID, or slug. Use this endpoint when you need more than the lightweight identity fields from the company list. Every lookup method returns the same full `company` detail payload, including: * Identity and profile fields such as name, domain, type, description, logo, and headquarters * Founders, CEOs, legal entities, categories, and social links * Latest available revenue, valuation, and total funding figures * Related Sacra research documents and time-series datasets * Exchange listings and company milestones, when available Arrays such as `company_datasets`, `documents`, `listings`, and `milestones` can be empty when Sacra does not have that type of data for a company. ## Choose an identifier | Identifier | Request | | ------------- | -------------------------------------------------- | | Domain | `GET /api/v1/companies/?company_domain=stripe.com` | | Numeric ID | `GET /api/v1/companies/?id=112` | | Slug in path | `GET /api/v1/companies/stripe/` | | Slug in query | `GET /api/v1/companies/?company_slug=stripe` | Use the domain when you need an identifier that works across Sacra endpoints. Pass the bare domain, such as `stripe.com`, without a protocol or path. Sacra can also resolve a known alternative domain to its company profile. Use the slug path when you already have the `slug` from a company response or want a readable resource URL. Use the numeric ID when your integration stores Sacra IDs as foreign keys. Provide exactly one of `company_domain`, `id`, or `company_slug`. Do not combine a company identifier with `mode=sync`. ## Get by domain ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/?company_domain=stripe.com" ``` ## Get by ID ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/?id=112" ``` ## Get by slug ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/stripe/" ``` The OpenAPI operation below documents this path-based slug lookup. Domain, ID, and query-slug lookups use `/api/v1/companies/` but return the same detail schema. # List companies - Companies API Source: https://docs.sacra.com/api-reference/companies/list-companies openapi.json GET /api/v1/companies/ Discover Sacra's company coverage, retrieve one company, or find companies with recently updated data. Use this endpoint to discover the companies Sacra covers or identify companies whose research and data changed during a time window. The request supports three response modes: | Goal | Request | Response | | ------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------- | | List Sacra's company coverage | Omit all query parameters | A `companies` collection with each company's ID, name, and domain | | Retrieve one company | Pass `company_domain`, `id`, or `company_slug` | A full `company` detail object | | Find recently updated companies | Pass `mode=sync` and an update window | A paginated `companies` collection with update metadata | Looking for one company? See [Get company detail](/api-reference/companies/get-a-company-detail) for lookup by domain, ID, or slug. The query identifier parameters shown below return a single `company` object rather than filtering the collection. Provide exactly one of `company_domain`, `id`, or `company_slug`. Do not combine a company identifier with `mode=sync`. ## List company coverage Call the endpoint without query parameters to return all active companies in Sacra's coverage universe. The lightweight response is useful for populating a company picker or building a local mapping between company IDs and domains. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/" ``` ## Find recently updated companies Set `mode=sync` to find companies whose selected data sources changed during an ISO 8601 time window. Each result includes `updated_at` and `updated_sources`, so you can decide which company or downstream resource to refresh. A sync window can span no more than 14 days. Use `sources` to monitor one or more comma-separated sources, such as `documents,news,metrics`. Use `sources=all` to include every supported source. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/?mode=sync&updated_at_gte=2026-08-11T00:00:00Z&updated_at_lte=2026-08-12T00:00:00Z&sources=all" ``` Sync responses contain up to 30 companies by default and support a maximum page size of 100. Follow `pagination.next_link` until it is `null` to retrieve every company in the window. The link preserves the time window, source filters, page size, and cursor for the next request. # Rank companies - Companies API Source: https://docs.sacra.com/api-reference/companies/rank-companies openapi.json GET /api/v1/companies/rankings/ Build a ranked list of active companies by valuation, revenue, or total funding. Use this endpoint to build company leaderboards, screen a market, or monitor the companies with the highest or lowest financial metrics. Choose `valuation`, `revenue`, or `total_funding` with `sort_by`, then narrow the results by company type, sort order, and result limit. The response includes the company identity, the metric used for ranking, its numeric value, and the date associated with that value. It also returns metadata that summarizes the applied ranking options and the total number of companies with a value for the selected metric. Companies without that metric are not included in the ranking. By default, the endpoint returns up to 50 companies ranked by valuation in descending order. You can request up to 100 results. For example, use the following query to return the 25 highest-valued private companies: ```bash theme={null} curl --request GET \ --url 'https://sacra.com/api/v1/companies/rankings/?sort_by=valuation&company_type=private&order=desc&limit=25' \ --header 'Authorization: Token YOUR_API_KEY' ``` By default, rankings exclude companies that are targets of active, closed [acquisitions](/concepts/events#acquisitions). Pass `include_acquired=true` to include them. Announced or cancelled deals do not trigger this exclusion. This option does not require the Events beta flag. # Get document detail - Documents API Source: https://docs.sacra.com/api-reference/documents/get-a-document openapi.json GET /api/v1/documents/{document_slug}/ Retrieve one document's full content by slug. The document slug is the only supported direct document lookup. Read the `slug` field from an item returned by [List documents](/api-reference/documents/list-documents), then pass it in the URL path: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/documents/kraken-at-1-5b-up-128-yoy/" ``` The response contains the document's full content, sections, table of contents, metadata, preview information, and delivery URLs. # List documents - Documents API Source: https://docs.sacra.com/api-reference/documents/list-documents openapi.json GET /api/v1/documents/ List documents globally or filter the collection by company. This endpoint always returns a `documents` collection. * Pass `company_domain` or `company_id` to list documents related to one company. * Omit company filters and provide a date range to list documents globally. Company filters can reduce the result count, but they do not retrieve a single document or change the response into a detail object. To retrieve one document, use its slug with [Get document detail](/api-reference/documents/get-a-document). # Search documents and content - Documents API Source: https://docs.sacra.com/api-reference/documents/search openapi.json POST /api/v1/search/ Performs a full-text search across document and explore indices, returning a unified, paginated list of results. **How pagination works:** 1. Results from the **document index** are returned first 2. Once exhausted, results from the **explore index** follow 3. Use `offset` and `limit` to page through the combined set Date filters are supported via `date_gte` and `date_lte`. # Create or retrieve a chart embed - Embeds API Source: https://docs.sacra.com/api-reference/embeds/create-or-retrieve-a-chart-embed openapi.json PUT /api/v1/embed/charts/ Creates a new chart (or retrieves an existing one) from one or more datasets and returns embeddable HTML. If a chart with the same name, description, and creator already exists, returns the existing embed with a 200. Otherwise creates a new chart and returns 201. # Get a company data summary embed - Embeds API Source: https://docs.sacra.com/api-reference/embeds/get-a-company-data-summary-embed openapi.json GET /api/v1/embed/company-data-summary/ Returns embeddable HTML for a company's data summary. Provide at least one of `company_slug`, `company_domain`, or `company_id`. If multiple are provided, `company_id` takes priority, followed by `company_slug`. # Get a company valuation chart embed - Embeds API Source: https://docs.sacra.com/api-reference/embeds/get-a-company-valuation-chart-embed openapi.json GET /api/v1/embed/company-data-valuation-chart/ Returns embeddable HTML for a company's valuation chart. Provide at least one of `company_slug`, `company_domain`, or `company_id`. If multiple are provided, `company_id` takes priority, followed by `company_slug`. # Get a company valuation table embed - Embeds API Source: https://docs.sacra.com/api-reference/embeds/get-a-company-valuation-table-embed openapi.json GET /api/v1/embed/company-data-valuation-table/ Returns embeddable HTML for a company's valuation table. Provide at least one of `company_slug`, `company_domain`, or `company_id`. If multiple are provided, `company_id` takes priority, followed by `company_slug`. # Get a document PDF embed - Embeds API Source: https://docs.sacra.com/api-reference/embeds/get-a-document-pdf-embed openapi.json GET /api/v1/embed/document-pdfs/ Returns embeddable HTML for a document's PDF viewer. Requires a `document_slug` to identify the document. # Get aggregated events - Events API Source: https://docs.sacra.com/api-reference/events/get-aggregated-events openapi.json GET /api/v1/events/ Returns aggregated events from funding rounds, secondary transactions, company milestones, corporate actions, and beta-gated acquisitions in chronological order. **Pagination modes:** - `page` (default): Offset-based pagination via `page` and `page_size`. - `cursor`: Cursor-based pagination via `page_after` / `page_before`. Recommended. **Global queries** (no company filter) require at least one date range (`start_date`, `created_at_gte`, or `updated_at_gte`) spanning 14 days or less. **Acquisitions beta:** Use `betas=acquisitions` (v1 only), optionally with `types=acquisition`. Company filters match the acquired company, not the buyer. Closed deals with unknown closing dates have `event_date=null` and are excluded by occurrence-date filters; use update-time filters to sync them. **API versioning:** Defaults to v1 (snake_case, detailed status). Pass `api_version=v0` for the deprecated legacy schema (kebab-case, binary status). Acquisitions are excluded by default. To include them, add `betas=acquisitions`; optionally add `types=acquisition` to return only acquisitions. The beta requires API v1. Company filters match the acquired company. See [Events](/concepts/events#acquisitions) for an overview and the response schema below for the payload. # Get aggregated events (batch) - Events API Source: https://docs.sacra.com/api-reference/events/get-aggregated-events-batch openapi.json POST /api/v1/events/ Same as GET but accepts a JSON body. Use for large multi-company queries that exceed URL length limits. **Pagination:** Prefer `page` (default): increment `page` while `pagination.has_next` is true. POST cursor responses always have null `next_link` and `prev_link`; GET returns navigation URLs. **Global queries** (no company filter) require at least one date range spanning 14 days or less. **Acquisitions beta:** Send `betas: ["acquisitions"]` (v1 only), optionally with `types: "acquisition"`. Company filters match the acquired company, not the buyer. Closed deals with unknown closing dates have `event_date=null` and are excluded by occurrence-date filters; use update-time filters to sync them. **API versioning:** Defaults to v1. Pass `api_version=v0` for deprecated legacy schema. Acquisitions are excluded by default. To include them, send `"betas": ["acquisitions"]` in the JSON body; optionally add `"types": "acquisition"` to return only acquisitions. A scalar `betas` string is invalid for POST. The beta requires API v1. See [Events](/concepts/events#acquisitions) for an overview and the response schema below for the payload. For batch pagination, use `pagination=page` (the default) and increment `page` while `pagination.has_next` is `true`. POST cursor responses have null `next_link` and `prev_link`; they do not provide the navigation URLs available with GET. # Get company filings - Filings API Source: https://docs.sacra.com/api-reference/filings/get-company-filings openapi.json GET /api/v1/filings/ Returns filings for a specific company with cursor-based pagination. Requires either `company_domain` or `company_id`. # Get company filings (batch) - Filings API Source: https://docs.sacra.com/api-reference/filings/get-company-filings-post openapi.json POST /api/v1/filings/ Same as GET but accepts a JSON body. Requires either `company_domain` or `company_id`. # Get funding rounds for a company - Funding API (legacy) Source: https://docs.sacra.com/api-reference/funding-legacy/get-funding-rounds-for-a-company openapi.json GET /api/v1/funding-rounds/ Returns the full funding round history for a company, including round type, share details, and citation sources. Identify the company by `company_domain` or `company_id` (at least one required). # Introduction - API reference Source: https://docs.sacra.com/api-reference/introduction Access private company data, research, and financial metrics via the Sacra API The Sacra API gives you programmatic access to private company intelligence: revenue estimates, valuations, funding rounds, research documents, events, and financial metrics — all in JSON over HTTPS. ## Base URL All requests go to: ``` https://sacra.com/api/v1/ ``` ## Authentication Every request requires an API key passed in the `Authorization` header: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/?company_domain=stripe.com" ``` Create and manage API keys in your [organization settings](https://sacra.com/orgs/settings/general/). Never expose your API key in client-side code. All requests should be made server-side. ## Endpoints Look up companies by domain. Returns profiles, revenue estimates, valuations, and metadata. Browse market research reports, company one-pagers, and expert interviews. Funding rounds, secondary transactions, corporate actions, and company milestones. SEC and regulatory filings for private companies. Detailed financial metrics with historical data and source citations. Ready-made embeddable widgets for valuation charts, data summaries, and research PDFs. Browse companies by category or sector. Deprecated funding round endpoints. Use Events instead. For a conceptual overview of the main data types, see [Companies](/concepts/companies), [Revenue](/concepts/revenue), [Events](/concepts/events), [Documents](/concepts/documents), and [News](/concepts/news). ## Pagination Most list endpoints return paginated results. Two pagination styles are used depending on the endpoint. **Cursor-based** (documents, events, metrics, news): ```json theme={null} { "pagination": { "page_size": 30, "total_items": 142, "next_link": "https://sacra.com/api/v1/documents/?page_after=abc123", "prev_link": null, "after_cursor": "abc123", "before_cursor": null } } ``` Use `page_after` and `page_before` to move through results. Follow `next_link` directly — it includes all query parameters. **Offset-based** (categories): ```json theme={null} { "pagination": { "limit": 20, "offset": 0, "total": 85, "next_offset": 20 } } ``` ## Rate limits Rate limits vary by plan. See [Pricing](https://sacra.com/pricing) for plan details, or contact [support](https://support.sacra.com/) with questions. # Get metric observations - Metrics API Source: https://docs.sacra.com/api-reference/metrics/get-metric-observations openapi.json GET /api/v1/metrics/ Returns metric observations with citations for one or more companies, with cursor-based pagination. **Company filters:** Provide single-company filters (`company_id`, `company_domain`) or multi-company filters (`company_ids`, `company_domains`), but not both. GET requests support up to 200 companies. **Global queries** (no company filter) require at least one date range (`measurement_end_date`, `comparison_window_end_date`, `created_at`, or `updated_at`) spanning 14 days or less. # Get metric observations (batch) - Metrics API Source: https://docs.sacra.com/api-reference/metrics/get-metric-observations-batch openapi.json POST /api/v1/metrics/ Same as GET but accepts a JSON body. Use for large multi-company queries. **Company filters:** Provide single-company filters (`company_id`, `company_domain`) or multi-company filters (`company_ids`, `company_domains`), but not both. **Global queries** (no company filter) require at least one date range (`measurement_end_date`, `comparison_window_end_date`, `created_at`, or `updated_at`) spanning 14 days or less. # Get company news - News API Source: https://docs.sacra.com/api-reference/news/get-company-news openapi.json GET /api/v1/news/company/ Returns news items for one or more companies with cursor-based pagination. **Company filter precedence:** `company_id` > `company_domains` > `company_domain`. If none are provided (domain-less query), at least one date range spanning 14 days or less is required. **Limits:** Up to 200 company domains. # Get company news (batch) - News API Source: https://docs.sacra.com/api-reference/news/get-company-news-batch openapi.json POST /api/v1/news/company/ Same as GET but accepts a JSON body. Use for large `company_domains` lists that exceed URL length limits. **Company filter precedence:** `company_id` > `company_domains` > `company_domain`. If none are provided (domain-less query), at least one date range spanning 14 days or less is required. **Limits:** Up to 1,000 company domains. # Content synchronization updates - Changelog Source: https://docs.sacra.com/changelog/content-sync Additive changes to /documents, /news/company, and /events for content synchronization workflows This changelog summarizes the additive changes to `/documents`, `/news/company`, and `/events` that enable content synchronization workflows. For a practical guide using these features, see [Sync Sacra Research & Data](/guides/syncing-data). ## Common additions All three endpoints now support: * **Time filters**: `created_at_gte`, `created_at_lte`, `updated_at_gte`, `updated_at_lte` * **Cursor pagination** (documents and news by default, events via `pagination=cursor`): `page_after`, `page_before`, `page_size` Cursor pagination responses include `next_link` / `prev_link` and cursor metadata. Cursor links URL-encode date values (e.g., `:` becomes `%3A`), which is expected. For daily polls, use a 24-hour window (tight date range). *** ## Documents **Additions:** * Global GET (no company params required) * `created_at_gte/lte` and `updated_at_gte/lte` filters * Cursor pagination (`page_after`, `page_before`, `page_size`) * Global responses include `companies` array with `relation` (`subject`/`connected`) * Company-scoped responses now include `published_at`, `created_at`, `updated_at` ### Global documents (no company params) ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/documents?updated_at_gte=2026-01-13T00:00:00Z&updated_at_lte=2026-01-14T00:00:00Z" ``` ```json theme={null} { "documents": [ { "id": 1835, "slug": "owner", "title": "Owner One-Pager", "link": "https://sacra-pdfs.s3.us-east-2.amazonaws.com/owner.pdf", "type": "company", "date": "2026-01-13", "published_at": "2026-01-13", "created_at": "2025-03-10T20:42:33.911Z", "updated_at": "2026-01-13T21:01:20.492Z", "preview_meta": { "title": "Owner", "image": "https://images.prismic.io/sacra/...", "description": "Software suite for restaurants to manage online ordering, websites, marketing, and loyalty" }, "companies": [ { "id": 1486, "domain": "owner.com", "relation": "subject" } ] } ], "pagination": { "page_size": 30, "current_page_items": 1, "total_items": 1, "next_link": null, "prev_link": null, "after_cursor": "Start", "before_cursor": null } } ``` ### Company-scoped documents ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/documents?company_domain=owner.com&updated_at_gte=2026-01-13T00:00:00Z&updated_at_lte=2026-01-14T00:00:00Z" ``` ```json theme={null} { "documents": [ { "id": 1835, "slug": "owner", "title": "Owner One-Pager", "link": "https://sacra-pdfs.s3.us-east-2.amazonaws.com/owner.pdf", "type": "company", "date": "2026-01-13", "published_at": "2026-01-13", "created_at": "2025-03-10T20:42:33.911Z", "updated_at": "2026-01-13T21:01:20.492Z", "preview_meta": { "title": "Owner", "image": "https://images.prismic.io/sacra/...", "description": "Software suite for restaurants to manage online ordering, websites, marketing, and loyalty" }, "relation": "subject" } ] } ``` *** ## News **Additions:** * `created_at_gte/lte` and `updated_at_gte/lte` filters (aliases for existing created\_at filters) * `company` object per item (`id`, `domain`) * Domain-less queries require a date window of 14 days or less Use daily polling with a 24-hour date window for domain-less queries. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/news/company?updated_at_gte=2026-01-13T00:00:00Z&updated_at_lte=2026-01-14T00:00:00Z" ``` ```json theme={null} { "company_news": [ { "id": "997bdd91-ec86-4f54-ac46-671eb50ec214", "release_date": "2026-01-13T10:37:38Z", "headline": "Balderton Capital Cashes Out $2 Billion From Revolut Stake", "short_headline": "Balderton Cashes $2B", "description": "It led Revolut's first funding round and has cashed out about $2bn...", "created_at": "2026-01-13T12:24:06.621470Z", "updated_at": "2026-01-13T12:24:06.621479Z", "articles": [ { "id": "0681f131-b451-43d6-a3f6-c857060021ee", "link": "https://ft.com/content/e19a419f-5c81-4326-8f41-478e90c7211a", "headline": "The London investor making billions from Revolut", "short_summary": "The VC firm Balderton Capital is cashing in on its home-run bet on the fintech", "date_published": "2026-01-14T05:00:31Z", "thumbnail": "...", "publication": "Financial Times", "publication_score": 200 } ], "company": { "id": 407, "domain": "revolut.com" } } ], "pagination": { "page_size": 10, "current_page_items": 7, "total_items": 7, "next_link": null, "prev_link": null, "after_cursor": "Start", "before_cursor": null }, "meta": { "query_type": "domain-less", "companies_count": 1276, "companies": null } } ``` *** ## Events **Additions:** * `created_at_gte/lte` and `updated_at_gte/lte` filters * Cursor pagination via `pagination=cursor` * Cursor pagination metadata aligned with documents/news (`next_link`, `prev_link`, cursors) Cursor pagination is opt-in via `pagination=cursor`. Page-based pagination remains the default. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/events?pagination=cursor&updated_at_gte=2026-01-13T00:00:00Z&updated_at_lte=2026-01-14T00:00:00Z" ``` ```json theme={null} { "events": [ { "event_id": "st_0c601c12-6213-4093-8e5b-90febbb1056e", "event_type": "secondary_transaction", "event_subtype": "institutional_secondary", "event_name": "Direct Sale (2025)", "event_date": "2025-09-01", "event_status": "closed", "event_last_updated_at": "2026-01-13T18:03:42.923112+00:00", "company": { "id": "407", "slug": "revolut", "domain": "revolut.com" }, "data": { "id": "0c601c12-6213-4093-8e5b-90febbb1056e", "updated_at": "2026-01-13T18:03:42.923112+00:00", "name": "Direct Sale (2025)", "transaction_type": "institutional_secondary", "transaction_amount": "1000000000.00", "currency": "USD", "valuation": "75000000000.00", "price_per_share": "1381.06", "announced_date": "2025-09-01", "closing_date": "2025-09-05", "created_at": "2025-10-24T01:19:34.954929+00:00", "equities": [], "status": "closed" } } ], "pagination": { "page_size": 30, "current_page_items": 1, "total_items": 1, "after_cursor": "Start", "before_cursor": null, "next_link": null, "prev_link": null } } ``` *** ## Notes * All changes are additive. Existing clients can continue using company-scoped queries and page-based events pagination. * Cursor pagination responses use endpoint-specific `next_link` and `prev_link` URLs. * Document content (document elements/body) is still served by the document content endpoint, not the global documents list. # Events v0 (MVP) to v1 - Changelog Source: https://docs.sacra.com/changelog/events-v1 Migration guide and changelog for the Events API v1 schema ## Executive summary The Events API is introducing a final v1 schema to improve data accuracy, consistency, and clarity. This document outlines all changes between the legacy v0 MVP schema and the new v1 schema. **v1 became the default on November 19.** ### What's changing * **Event type format**: kebab-case to snake\_case (`funding-round` to `funding_round`) * **Status terminology**: `planned` to `announced` for clarity * **Round type accuracy**: Generic `equity` type split into specific `growth` and `crowdfunding` types * **Model separation**: `CorporateAction` now distinct from `CompanyMilestone` * **New fields**: `event_name` and `event_status` at envelope level, `closing_date` for SecondaryTransactions, `is_extension` for FundingRounds ### Migration timeline * **Current status**: v1 is opt-in via `?version=v1` query parameter * **Default**: v0 schema (for backward compatibility) * **Migration period**: v1 default will be in effect November 19 * **Future**: v1 will become default (v0 will be deprecated but you can still query for v0) ### Impact assessment * **Breaking changes**: Yes -- response format changes require client code updates * **Backward compatibility**: v0 remains default during migration period * **Action required**: Test with `?version=v1`, update client code, migrate before deadline *** ## Breaking changes ### 1. Event type format change Event types have changed from kebab-case to snake\_case for consistency with industry standards. | Entity | v0 (Legacy) | v1 | | -------------------- | ----------------------- | ----------------------- | | FundingRound | `funding-round` | `funding_round` | | SecondaryTransaction | `secondary-transaction` | `secondary_transaction` | | CorporateAction | `company-milestone` | `corporate_action` | | CompanyMilestone | `company-milestone` | `company_milestone` | **Impact**: Code that checks `event_type` in responses must be updated. ```python theme={null} # v0 if event['event_type'] == 'funding-round': process_funding_round(event) # v1 if event['event_type'] == 'funding_round': process_funding_round(event) ``` The `types` **query parameter** still uses kebab-case in both v0 and v1 (e.g. `?types=funding-round`). Only the `event_type` field in the **response** changed to snake\_case. In v0, `CorporateAction` and `CompanyMilestone` were both returned as `company-milestone`. In v1, they are distinct types. *** ### 2. Status field terminology The status terminology has changed from `planned` to `announced` for better clarity about event lifecycle. | Status meaning | v0 (Legacy) | v1 | | --------------------------- | ----------- | ----------- | | Announced but not completed | `planned` | `announced` | | Completed/finalized | `closed` | `closed` | | Cancelled/abandoned | `cancelled` | `cancelled` | ```python theme={null} # v0 if event['data']['status'] == 'planned': mark_as_upcoming(event) # v1 if event['data']['status'] == 'announced': mark_as_upcoming(event) ``` *** ### 3. Round type accuracy v1 exposes accurate round types instead of generic mappings. The generic `equity` type has been split into specific types. | Actual round type | v0 (Legacy) | v1 | | ----------------- | --------------------- | --------------------- | | Growth round | `equity` | `growth` | | Crowdfunding | `equity` | `crowdfunding` | | Strategic | `strategic` | `strategic` | | Seed | `seed` | `seed` | | Series A-N | `series_a`-`series_n` | `series_a`-`series_n` | **Impact**: Generic `equity` type no longer exists in v1. Clients filtering or processing by round type must update logic. ```python theme={null} # v0 if event['data']['round_type'] == 'equity': # Could be growth OR crowdfunding - ambiguous process_equity_round(event) # v1 if event['data']['round_type'] in ['growth', 'crowdfunding']: if event['data']['round_type'] == 'growth': process_growth_round(event) elif event['data']['round_type'] == 'crowdfunding': process_crowdfunding_round(event) ``` *** ### 4. CorporateAction vs CompanyMilestone separation v1 introduces a distinct `CorporateAction` entity type, separating capital structure changes from general company milestones. **v0**: Both corporate actions (stock splits, recaps) and company milestones (IPOs, incorporations) returned as `company-milestone`. **v1**: Distinct types: * `corporate_action`: Stock splits, reverse splits, recapitalizations * `company_milestone`: IPOs, incorporations, delistings **Impact**: Filtering by `types=company-milestone` in v0 returned both. In v1, you must specify which type you want. ```bash theme={null} # v0 (gets both corporate actions and milestones) GET /api/v1/events/?types=company-milestone # v1 (must specify which you want) GET /api/v1/events/?version=v1&types=corporate-action GET /api/v1/events/?version=v1&types=company-milestone GET /api/v1/events/?version=v1&types=corporate-action,company-milestone ``` *** ### 5. New field: `event_status` at envelope level v1 adds `event_status` at the event envelope level (in addition to `data.status`) for easier filtering without parsing nested data. ```json theme={null} // v0 - No event_status at top level { "event_id": "fr_abc123", "event_type": "funding-round", "event_date": "2024-10-02", "data": { "status": "closed" } } ``` ```json theme={null} // v1 - event_status at envelope level { "event_id": "fr_abc123", "event_type": "funding_round", "event_date": "2024-10-02", "event_status": "closed", "data": { "status": "closed" } } ``` *** ### 6. New field: `closing_date` for SecondaryTransactions v1 adds the `closing_date` field to SecondaryTransaction events to distinguish between announcement and completion dates. **Smart inference**: If `event_status: "closed"` but `closing_date` is null, the API automatically sets `closing_date = announced_date` in the response (indicating "we know it closed, but only have one date"). ```json theme={null} // v0 - No closing_date field { "event_type": "secondary-transaction", "data": { "announced_date": "2024-08-15", "status": "closed" } } ``` ```json theme={null} // v1 - closing_date available { "event_type": "secondary_transaction", "event_status": "closed", "data": { "announced_date": "2024-08-15", "closing_date": "2024-09-29", "status": "closed" } } ``` ```json theme={null} // v1 - closing_date inferred (when only one date known) { "event_type": "secondary_transaction", "event_status": "closed", "data": { "announced_date": "2024-11-27", "closing_date": "2024-11-27", "status": "closed" } } ``` *** ### 7. New field: `event_name` at envelope level v1 adds `event_name` to the event envelope for easier timeline/visualization rendering without parsing nested data. ```json theme={null} // v0 - Name buried in nested data { "event_id": "fr_abc123", "event_type": "funding-round", "event_date": "2024-10-02", "data": { "name": "Series A 2024" } } ``` ```json theme={null} // v1 - Name at envelope level { "event_id": "fr_abc123", "event_type": "funding_round", "event_name": "Series A 2024", "event_date": "2024-10-02", "data": { "name": "Series A 2024" } } ``` Use case -- timeline visualization: ```javascript theme={null} // v1 - Clean timeline rendering with just envelope data events.map(e => ({ date: e.event_date, name: e.event_name, type: e.event_type })) // v0 - Requires parsing nested data events.map(e => ({ date: e.event_date, name: e.data.name || e.data.label, type: e.event_type })) ``` *** ### 8. New field: `is_extension` for FundingRounds v1 adds the `is_extension` boolean field to identify funding rounds that extend or follow on from a previous round. Use cases: * Identify multiple closes of the same series * Calculate total capital by series (base + extensions) * Detect reclassified growth rounds ```json theme={null} // v0 - No way to distinguish base vs extension rounds { "event_type": "funding-round", "data": { "round_type": "series_e", "amount_raised": "500000000.00" } } ``` ```json theme={null} // v1 - is_extension field identifies extensions { "event_type": "funding_round", "data": { "round_type": "series_e", "amount_raised": "500000000.00", "is_extension": true } } ``` *** ## Side-by-side field comparison ### Event envelope fields | Field | v0 | v1 | Notes | | ----------------------- | ---------------- | ----------------- | -------------------------- | | `event_id` | Yes | Yes | Unchanged | | `event_type` | Yes (kebab-case) | Yes (snake\_case) | Format changed | | `event_subtype` | Yes | Yes | May differ for round types | | `event_name` | No | Yes | **New** in v1 | | `event_date` | Yes | Yes | Unchanged | | `event_status` | No | Yes | **New** in v1 | | `event_last_updated_at` | Yes | Yes | Unchanged | | `company` | Yes | Yes | Unchanged | | `data` | Yes | Yes | Structure varies by type | ### FundingRound data fields | Field | v0 | v1 | Notes | | ---------------- | ---------------------- | -------------------------------------- | ------------------- | | `id` | Yes | Yes | Unchanged | | `name` | Yes | Yes | Unchanged | | `round_type` | Yes (`equity` generic) | Yes (`growth`/`crowdfunding` specific) | More accurate in v1 | | `amount_raised` | Yes | Yes | Unchanged | | `currency` | Yes | Yes | Unchanged | | `valuation` | Yes | Yes | Unchanged | | `announced_date` | Yes | Yes | Unchanged | | `equities` | Yes | Yes | Unchanged | | `status` | Yes (`planned`) | Yes (`announced`) | Terminology changed | | `is_extension` | No | Yes | **New** in v1 | | `created_at` | Yes | Yes | Unchanged | | `updated_at` | Yes | Yes | Unchanged | ### SecondaryTransaction data fields | Field | v0 | v1 | Notes | | -------------------- | --------------- | ----------------- | ------------------- | | `id` | Yes | Yes | Unchanged | | `name` | Yes | Yes | Unchanged | | `transaction_type` | Yes | Yes | Unchanged | | `transaction_amount` | Yes | Yes | Unchanged | | `currency` | Yes | Yes | Unchanged | | `valuation` | Yes | Yes | Unchanged | | `price_per_share` | Yes | Yes | Unchanged | | `announced_date` | Yes | Yes | Unchanged | | `closing_date` | No | Yes | **New** in v1 | | `status` | Yes (`planned`) | Yes (`announced`) | Terminology changed | | `created_at` | Yes | Yes | Unchanged | | `updated_at` | Yes | Yes | Unchanged | ### CorporateAction (v1) vs CompanyMilestone (v0) In v0, corporate actions were returned as `company-milestone` with a simplified schema. In v1, they have their own distinct type and richer schema. v0 schema (as `company-milestone`): ```json theme={null} { "event_type": "company-milestone", "event_subtype": "stock_split", "data": { "id": "...", "type": "stock_split", "date": "2019-03-01", "label": "Stock Split", "description": "2-for-1 stock split", "data": {"split_ratio": "2:1"} } } ``` v1 schema (as `corporate_action`): ```json theme={null} { "event_type": "corporate_action", "event_subtype": "stock_split", "event_status": "closed", "data": { "id": "...", "name": "2-for-1 Stock Split", "type": "stock_split", "announced_date": "2019-02-15", "effective_date": "2019-03-01", "description": "2-for-1 stock split", "data": {"split_ratio": "2:1"}, "status": "closed" } } ``` Key differences: 1. `event_type` changed from `company-milestone` to `corporate_action` 2. New `announced_date` field (separate from `effective_date`) 3. New `event_status` at envelope level 4. `name` field replaces simplified `label` 5. `status` field added to data *** ## Complete migration example ### v0 response (legacy) ```json theme={null} { "events": [ { "event_id": "fr_7d94ae1b-b989-4345-af37-19a78068c5eb", "event_type": "funding-round", "event_subtype": "series_e", "event_date": "2025-07-30", "event_last_updated_at": "2025-10-27T13:38:35.316863+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "7d94ae1b-b989-4345-af37-19a78068c5eb", "updated_at": "2025-10-27T13:38:35.316863+00:00", "name": "Series E (2025) Extension", "round_type": "series_e", "amount_raised": "500000000.00", "currency": "USD", "valuation": "22500000000.00", "announced_date": "2025-07-30", "equities": [ { "name": "Series E-2", "equity_type": "preferred", "round_type": "series_e", "issue_price": "65.0000000", "issued_at": "2025-07-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.038010+00:00" } ], "status": "closed" } }, { "event_id": "fr_ca9560a0-8793-493c-8ced-64be4a290161", "event_type": "funding-round", "event_subtype": "series_e", "event_date": "2025-06-17", "event_last_updated_at": "2025-10-24T01:12:18.330534+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "ca9560a0-8793-493c-8ced-64be4a290161", "updated_at": "2025-10-24T01:12:18.330534+00:00", "name": "Series E (2025)", "round_type": "series_e", "amount_raised": "200000000.00", "currency": "USD", "valuation": "16000000000.00", "announced_date": "2025-06-17", "equities": [ { "name": "Series E", "equity_type": "preferred", "round_type": "series_e", "issue_price": "47.5000000", "issued_at": "2025-06-30T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.034948+00:00" } ], "status": "closed" } }, { "event_id": "st_a7cecea9-634d-494d-bd0a-45779d4099a5", "event_type": "secondary-transaction", "event_subtype": "tender_offer", "event_date": "2025-03-03", "event_last_updated_at": "2025-10-24T01:12:36.485984+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "a7cecea9-634d-494d-bd0a-45779d4099a5", "updated_at": "2025-10-24T01:12:36.485984+00:00", "name": "Tender Offer (2025)", "transaction_type": "tender_offer", "transaction_amount": null, "currency": "USD", "valuation": "13000000000.00", "price_per_share": null, "announced_date": "2025-03-03", "created_at": "2025-10-24T01:12:36.478896+00:00", "status": "closed" } }, { "event_id": "fr_2464d613-61d6-4bee-86c7-0ddf84f674b2", "event_type": "funding-round", "event_subtype": "series_d", "event_date": "2024-04-17", "event_last_updated_at": "2025-10-27T13:38:31.212436+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "2464d613-61d6-4bee-86c7-0ddf84f674b2", "updated_at": "2025-10-27T13:38:31.212436+00:00", "name": "Series D (2024) Extension", "round_type": "series_d", "amount_raised": "150000000.00", "currency": "USD", "valuation": "7650000000.00", "announced_date": "2024-04-17", "equities": [ { "name": "Series D", "equity_type": "preferred", "round_type": "series_d", "issue_price": "20.0000000", "issued_at": "2024-04-25T19:16:00+00:00", "updated_at": "2025-10-24T01:18:05.027279+00:00" }, { "name": "Series D-2", "equity_type": "preferred", "round_type": "series_d", "issue_price": "25.0000000", "issued_at": "2024-04-25T19:16:00+00:00", "updated_at": "2025-10-24T01:18:05.031694+00:00" } ], "status": "closed" } }, { "event_id": "fr_35405edb-2e8a-4e07-b517-d080e0c832f0", "event_type": "funding-round", "event_subtype": "series_d", "event_date": "2023-08-22", "event_last_updated_at": "2025-10-24T01:14:33.375472+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "35405edb-2e8a-4e07-b517-d080e0c832f0", "updated_at": "2025-10-24T01:14:33.375472+00:00", "name": "Series D (2023)", "round_type": "series_d", "amount_raised": "300000000.00", "currency": "USD", "valuation": "5800000000.00", "announced_date": "2023-08-22", "equities": [], "status": "closed" } }, { "event_id": "fr_d3a7773c-e3df-4b9b-8711-8e699213c2b5", "event_type": "funding-round", "event_subtype": "series_c", "event_date": "2022-03-21", "event_last_updated_at": "2025-10-27T13:38:26.703499+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "d3a7773c-e3df-4b9b-8711-8e699213c2b5", "updated_at": "2025-10-27T13:38:26.703499+00:00", "name": "Growth (2022) Extension", "round_type": "series_c", "amount_raised": "200000000.00", "currency": "USD", "valuation": "8100000000.00", "announced_date": "2022-03-21", "equities": [ { "name": "Series C-3", "equity_type": "preferred", "round_type": "series_c", "issue_price": "30.0000000", "issued_at": "2022-03-31T04:00:00+00:00", "updated_at": "2025-10-24T01:19:34.939585+00:00" } ], "status": "closed" } }, { "event_id": "fr_362bcaa9-e77d-488b-8562-9aa2ccd4ec70", "event_type": "funding-round", "event_subtype": "series_c", "event_date": "2021-08-24", "event_last_updated_at": "2025-10-24T01:13:06.683649+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "362bcaa9-e77d-488b-8562-9aa2ccd4ec70", "updated_at": "2025-10-24T01:13:06.683649+00:00", "name": "Series C (2021)", "round_type": "series_c", "amount_raised": "300000000.00", "currency": "USD", "valuation": "3900000000.00", "announced_date": "2021-08-24", "equities": [ { "name": "Series C-2", "equity_type": "preferred", "round_type": "series_c", "issue_price": "6.6808000", "issued_at": "2021-08-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.017683+00:00" }, { "name": "Series C-1", "equity_type": "preferred", "round_type": "series_c", "issue_price": "15.0000000", "issued_at": "2021-08-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.023665+00:00" } ], "status": "closed" } }, { "event_id": "fr_c56cfcaa-a00b-4279-8ee2-413114a499d4", "event_type": "funding-round", "event_subtype": "series_b", "event_date": "2021-04-08", "event_last_updated_at": "2025-10-24T01:12:55.156817+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "c56cfcaa-a00b-4279-8ee2-413114a499d4", "updated_at": "2025-10-24T01:12:55.156817+00:00", "name": "Series B (2021)", "round_type": "series_b", "amount_raised": "115000000.00", "currency": "USD", "valuation": "1600000000.00", "announced_date": "2021-04-08", "equities": [ { "name": "Series B", "equity_type": "preferred", "round_type": "series_b", "issue_price": "4.7517200", "issued_at": "2021-04-30T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.012209+00:00" } ], "status": "closed" } }, { "event_id": "fr_6960aea5-9834-4c13-a39c-9e3a6d1b7c7c", "event_type": "funding-round", "event_subtype": "series_a", "event_date": "2020-08-01", "event_last_updated_at": "2025-10-27T13:38:20.319450+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "6960aea5-9834-4c13-a39c-9e3a6d1b7c7c", "updated_at": "2025-10-27T13:38:20.319450+00:00", "name": "Series A (2020) Extension", "round_type": "series_a", "amount_raised": "30000000.00", "currency": "USD", "valuation": null, "announced_date": "2020-08-01", "equities": [ { "name": "Series A-4", "equity_type": "preferred", "round_type": "series_a", "issue_price": "0.7105800", "issued_at": "2020-08-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:04.998671+00:00" }, { "name": "Series A-3", "equity_type": "preferred", "round_type": "series_a", "issue_price": "1.0213600", "issued_at": "2020-08-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.008617+00:00" } ], "status": "closed" } }, { "event_id": "fr_88b1a90e-0a20-4285-9eff-414b45573d4f", "event_type": "funding-round", "event_subtype": "series_a", "event_date": "2020-02-12", "event_last_updated_at": "2025-10-24T01:14:19.736753+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "88b1a90e-0a20-4285-9eff-414b45573d4f", "updated_at": "2025-10-24T01:14:19.736753+00:00", "name": "Series A (2020)", "round_type": "series_a", "amount_raised": "15000000.00", "currency": "USD", "valuation": null, "announced_date": "2020-02-12", "equities": [ { "name": "Series A-2", "equity_type": "preferred", "round_type": "series_a", "issue_price": "0.2561400", "issued_at": "2020-01-31T05:00:00+00:00", "updated_at": "2025-10-24T01:18:04.987879+00:00" }, { "name": "Series A-1", "equity_type": "preferred", "round_type": "series_a", "issue_price": "0.5763200", "issued_at": "2020-01-31T05:00:00+00:00", "updated_at": "2025-10-24T01:18:04.993509+00:00" } ], "status": "closed" } }, { "event_id": "fr_4f656e60-48be-4862-aaff-df62ffb9fa94", "event_type": "funding-round", "event_subtype": "seed", "event_date": "2019-08-01", "event_last_updated_at": "2025-10-24T01:13:18.484702+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "4f656e60-48be-4862-aaff-df62ffb9fa94", "updated_at": "2025-10-24T01:13:18.484702+00:00", "name": "Seed (2019)", "round_type": "seed", "amount_raised": "8000000.00", "currency": "USD", "valuation": null, "announced_date": "2019-08-01", "equities": [ { "name": "Series Seed", "equity_type": "preferred", "round_type": "seed", "issue_price": "0.2105000", "issued_at": "2019-06-30T04:00:00+00:00", "updated_at": "2025-10-24T01:18:04.982651+00:00" } ], "status": "closed" } } ], "pagination": { "page": 1, "page_size": 30, "total_pages": 1, "total_count": 11, "has_next": false, "has_previous": false } } ``` ### v1 response ```json theme={null} { "events": [ { "event_id": "fr_7d94ae1b-b989-4345-af37-19a78068c5eb", "event_type": "funding_round", "event_subtype": "series_e", "event_name": "Series E (2025) Extension", "event_date": "2025-07-30", "event_status": "closed", "event_last_updated_at": "2025-10-27T13:38:35.316863+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "7d94ae1b-b989-4345-af37-19a78068c5eb", "updated_at": "2025-10-27T13:38:35.316863+00:00", "name": "Series E (2025) Extension", "round_type": "series_e", "amount_raised": "500000000.00", "currency": "USD", "valuation": "22500000000.00", "announced_date": "2025-07-30", "equities": [ { "name": "Series E-2", "equity_type": "preferred", "round_type": "series_e", "issue_price": "65.0000000", "issued_at": "2025-07-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.038010+00:00" } ], "status": "closed", "is_extension": true } }, { "event_id": "fr_ca9560a0-8793-493c-8ced-64be4a290161", "event_type": "funding_round", "event_subtype": "series_e", "event_name": "Series E (2025)", "event_date": "2025-06-17", "event_status": "closed", "event_last_updated_at": "2025-10-24T01:12:18.330534+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "ca9560a0-8793-493c-8ced-64be4a290161", "updated_at": "2025-10-24T01:12:18.330534+00:00", "name": "Series E (2025)", "round_type": "series_e", "amount_raised": "200000000.00", "currency": "USD", "valuation": "16000000000.00", "announced_date": "2025-06-17", "equities": [ { "name": "Series E", "equity_type": "preferred", "round_type": "series_e", "issue_price": "47.5000000", "issued_at": "2025-06-30T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.034948+00:00" } ], "status": "closed", "is_extension": false } }, { "event_id": "st_a7cecea9-634d-494d-bd0a-45779d4099a5", "event_type": "secondary_transaction", "event_subtype": "tender_offer", "event_name": "Tender Offer (2025)", "event_date": "2025-03-03", "event_status": "closed", "event_last_updated_at": "2025-10-24T01:12:36.485984+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "a7cecea9-634d-494d-bd0a-45779d4099a5", "updated_at": "2025-10-24T01:12:36.485984+00:00", "name": "Tender Offer (2025)", "transaction_type": "tender_offer", "transaction_amount": null, "currency": "USD", "valuation": "13000000000.00", "price_per_share": null, "announced_date": "2025-03-03", "closing_date": "2025-03-03", "created_at": "2025-10-24T01:12:36.478896+00:00", "status": "closed" } }, { "event_id": "fr_2464d613-61d6-4bee-86c7-0ddf84f674b2", "event_type": "funding_round", "event_subtype": "series_d", "event_name": "Series D (2024) Extension", "event_date": "2024-04-17", "event_status": "closed", "event_last_updated_at": "2025-10-27T13:38:31.212436+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "2464d613-61d6-4bee-86c7-0ddf84f674b2", "updated_at": "2025-10-27T13:38:31.212436+00:00", "name": "Series D (2024) Extension", "round_type": "series_d", "amount_raised": "150000000.00", "currency": "USD", "valuation": "7650000000.00", "announced_date": "2024-04-17", "equities": [ { "name": "Series D", "equity_type": "preferred", "round_type": "series_d", "issue_price": "20.0000000", "issued_at": "2024-04-25T19:16:00+00:00", "updated_at": "2025-10-24T01:18:05.027279+00:00" }, { "name": "Series D-2", "equity_type": "preferred", "round_type": "series_d", "issue_price": "25.0000000", "issued_at": "2024-04-25T19:16:00+00:00", "updated_at": "2025-10-24T01:18:05.031694+00:00" } ], "status": "closed", "is_extension": true } }, { "event_id": "fr_35405edb-2e8a-4e07-b517-d080e0c832f0", "event_type": "funding_round", "event_subtype": "series_d", "event_name": "Series D (2023)", "event_date": "2023-08-22", "event_status": "closed", "event_last_updated_at": "2025-10-24T01:14:33.375472+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "35405edb-2e8a-4e07-b517-d080e0c832f0", "updated_at": "2025-10-24T01:14:33.375472+00:00", "name": "Series D (2023)", "round_type": "series_d", "amount_raised": "300000000.00", "currency": "USD", "valuation": "5800000000.00", "announced_date": "2023-08-22", "equities": [], "status": "closed", "is_extension": false } }, { "event_id": "fr_d3a7773c-e3df-4b9b-8711-8e699213c2b5", "event_type": "funding_round", "event_subtype": "series_c", "event_name": "Growth (2022) Extension", "event_date": "2022-03-21", "event_status": "closed", "event_last_updated_at": "2025-10-27T13:38:26.703499+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "d3a7773c-e3df-4b9b-8711-8e699213c2b5", "updated_at": "2025-10-27T13:38:26.703499+00:00", "name": "Growth (2022) Extension", "round_type": "series_c", "amount_raised": "200000000.00", "currency": "USD", "valuation": "8100000000.00", "announced_date": "2022-03-21", "equities": [ { "name": "Series C-3", "equity_type": "preferred", "round_type": "series_c", "issue_price": "30.0000000", "issued_at": "2022-03-31T04:00:00+00:00", "updated_at": "2025-10-24T01:19:34.939585+00:00" } ], "status": "closed", "is_extension": true } }, { "event_id": "fr_362bcaa9-e77d-488b-8562-9aa2ccd4ec70", "event_type": "funding_round", "event_subtype": "series_c", "event_name": "Series C (2021)", "event_date": "2021-08-24", "event_status": "closed", "event_last_updated_at": "2025-10-24T01:13:06.683649+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "362bcaa9-e77d-488b-8562-9aa2ccd4ec70", "updated_at": "2025-10-24T01:13:06.683649+00:00", "name": "Series C (2021)", "round_type": "series_c", "amount_raised": "300000000.00", "currency": "USD", "valuation": "3900000000.00", "announced_date": "2021-08-24", "equities": [ { "name": "Series C-2", "equity_type": "preferred", "round_type": "series_c", "issue_price": "6.6808000", "issued_at": "2021-08-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.017683+00:00" }, { "name": "Series C-1", "equity_type": "preferred", "round_type": "series_c", "issue_price": "15.0000000", "issued_at": "2021-08-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.023665+00:00" } ], "status": "closed", "is_extension": false } }, { "event_id": "fr_c56cfcaa-a00b-4279-8ee2-413114a499d4", "event_type": "funding_round", "event_subtype": "series_b", "event_name": "Series B (2021)", "event_date": "2021-04-08", "event_status": "closed", "event_last_updated_at": "2025-10-24T01:12:55.156817+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "c56cfcaa-a00b-4279-8ee2-413114a499d4", "updated_at": "2025-10-24T01:12:55.156817+00:00", "name": "Series B (2021)", "round_type": "series_b", "amount_raised": "115000000.00", "currency": "USD", "valuation": "1600000000.00", "announced_date": "2021-04-08", "equities": [ { "name": "Series B", "equity_type": "preferred", "round_type": "series_b", "issue_price": "4.7517200", "issued_at": "2021-04-30T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.012209+00:00" } ], "status": "closed", "is_extension": false } }, { "event_id": "fr_6960aea5-9834-4c13-a39c-9e3a6d1b7c7c", "event_type": "funding_round", "event_subtype": "series_a", "event_name": "Series A (2020) Extension", "event_date": "2020-08-01", "event_status": "closed", "event_last_updated_at": "2025-10-27T13:38:20.319450+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "6960aea5-9834-4c13-a39c-9e3a6d1b7c7c", "updated_at": "2025-10-27T13:38:20.319450+00:00", "name": "Series A (2020) Extension", "round_type": "series_a", "amount_raised": "30000000.00", "currency": "USD", "valuation": null, "announced_date": "2020-08-01", "equities": [ { "name": "Series A-4", "equity_type": "preferred", "round_type": "series_a", "issue_price": "0.7105800", "issued_at": "2020-08-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:04.998671+00:00" }, { "name": "Series A-3", "equity_type": "preferred", "round_type": "series_a", "issue_price": "1.0213600", "issued_at": "2020-08-31T04:00:00+00:00", "updated_at": "2025-10-24T01:18:05.008617+00:00" } ], "status": "closed", "is_extension": true } }, { "event_id": "fr_88b1a90e-0a20-4285-9eff-414b45573d4f", "event_type": "funding_round", "event_subtype": "series_a", "event_name": "Series A (2020)", "event_date": "2020-02-12", "event_status": "closed", "event_last_updated_at": "2025-10-24T01:14:19.736753+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "88b1a90e-0a20-4285-9eff-414b45573d4f", "updated_at": "2025-10-24T01:14:19.736753+00:00", "name": "Series A (2020)", "round_type": "series_a", "amount_raised": "15000000.00", "currency": "USD", "valuation": null, "announced_date": "2020-02-12", "equities": [ { "name": "Series A-2", "equity_type": "preferred", "round_type": "series_a", "issue_price": "0.2561400", "issued_at": "2020-01-31T05:00:00+00:00", "updated_at": "2025-10-24T01:18:04.987879+00:00" }, { "name": "Series A-1", "equity_type": "preferred", "round_type": "series_a", "issue_price": "0.5763200", "issued_at": "2020-01-31T05:00:00+00:00", "updated_at": "2025-10-24T01:18:04.993509+00:00" } ], "status": "closed", "is_extension": false } }, { "event_id": "fr_4f656e60-48be-4862-aaff-df62ffb9fa94", "event_type": "funding_round", "event_subtype": "seed", "event_name": "Seed (2019)", "event_date": "2019-08-01", "event_status": "closed", "event_last_updated_at": "2025-10-24T01:13:18.484702+00:00", "company": { "id": "65", "slug": "ramp", "domain": "ramp.com" }, "data": { "id": "4f656e60-48be-4862-aaff-df62ffb9fa94", "updated_at": "2025-10-24T01:13:18.484702+00:00", "name": "Seed (2019)", "round_type": "seed", "amount_raised": "8000000.00", "currency": "USD", "valuation": null, "announced_date": "2019-08-01", "equities": [ { "name": "Series Seed", "equity_type": "preferred", "round_type": "seed", "issue_price": "0.2105000", "issued_at": "2019-06-30T04:00:00+00:00", "updated_at": "2025-10-24T01:18:04.982651+00:00" } ], "status": "closed", "is_extension": false } } ], "pagination": { "page": 1, "page_size": 30, "total_pages": 1, "total_count": 11, "has_next": false, "has_previous": false } } ``` # Product updates - Changelog Source: https://docs.sacra.com/changelog/index New features, API changes, and improvements to the Sacra API ## PDF and filing links now use stable Sacra URLs Sacra API fields that previously linked directly to underlying PDF files now return stable Sacra URLs. The response field names are unchanged. If your backend downloads PDFs directly, make sure your HTTP client follows redirects. See the [stable PDF and filing URLs changelog](/changelog/stable-pdf-and-filing-urls) for affected fields and examples. ## Content synchronization updates Added time filters and cursor pagination to `/documents`, `/news/company`, and `/events` to support content synchronization workflows. All three endpoints now support: * Time filters: `created_at_gte`, `created_at_lte`, `updated_at_gte`, `updated_at_lte` * Cursor pagination via `page_after`, `page_before`, `page_size` (default for documents and news; opt-in via `pagination=cursor` for events) * Cursor responses include `next_link`, `prev_link`, and cursor metadata ### Documents * Global GET with no company params required * Global responses include a `companies` array with `relation` (`subject` / `connected`) * Company-scoped responses now include `published_at`, `created_at`, `updated_at` ### News * `company` object (`id`, `domain`) added per item * Domain-less queries require a date window of 14 days or less ### Events * Cursor pagination is opt-in via `pagination=cursor`; page-based pagination remains the default Cursor links URL-encode date values (e.g., `:` becomes `%3A`), which is expected. For daily polls, use a 24-hour window. All changes are additive — existing clients can continue using company-scoped queries and page-based events pagination without modification. ## Events API v1 is now the default The Events API v1 schema is now the default. v0 remains queryable via `?version=v0` but is deprecated. ### Breaking changes from v0 * **Event type format** — `event_type` values changed from kebab-case to snake\_case (e.g. `funding-round` → `funding_round`). Note: the `types` query parameter still uses kebab-case. * **Status terminology** — `planned` renamed to `announced` across all event types * **Round type accuracy** — the generic `equity` round type is replaced by `growth` and `crowdfunding` * **CorporateAction separation** — corporate actions (stock splits, recapitalizations) are now returned as `corporate_action` instead of `company-milestone` ### New fields * `event_name` at the event envelope level — simplifies timeline rendering without parsing nested data * `event_status` at the event envelope level — mirrors `data.status` for easier filtering * `closing_date` on SecondaryTransactions — distinguishes announcement from completion date; inferred from `announced_date` when only one date is known * `is_extension` on FundingRounds — identifies rounds that extend or follow on from a prior round See the [Events v1 migration guide](/changelog/events-v1) for a full field comparison and before/after examples. # PDF and filing links now use stable Sacra URLs - Changelog Source: https://docs.sacra.com/changelog/stable-pdf-and-filing-urls Sacra API PDF and filing links now resolve through stable Sacra URLs that redirect to temporary signed delivery URLs ## Summary As of Thursday, May 14, 2026 at 10:00 AM ET, Sacra API fields that previously linked directly to underlying PDF files for documents and filings now return stable Sacra URLs instead. The response field names are not changing. The main change is the URL behavior: ```text theme={null} Before: Sacra API -> direct S3 PDF URL After: Sacra API -> stable Sacra URL -> 302 redirect -> temporary signed PDF delivery URL ``` This lets Sacra stop exposing durable storage URLs while preserving the same API response shape for customers. Existing direct S3 links, such as `https://sacra-pdfs.s3.us-east-2.amazonaws.com/spacex.pdf`, will continue to work through **June 14, 2026**. After that date, Sacra will turn off support for old direct S3 links. If your integration renders or stores Sacra-provided file links, no change should be needed. If your backend downloads PDFs directly, confirm that your HTTP client follows redirects. *** ## Action required * If you render or store Sacra-provided PDF and filing links, no action should be required. * If you use Sacra PDF embeds, no action is needed. Existing embed HTML continues to point to Sacra's embed route; Sacra now renders the PDF inside that embed using the browser's native PDF viewer. * If your backend downloads PDFs directly, make sure your HTTP client follows redirects. * Keep using the stable Sacra URL returned by the API. * Do not store or hardcode the redirected delivery URL, since it is temporary. Most common HTTP clients already follow redirects for `GET` requests. The examples below show the main case that can break: clients or wrappers configured to stop at the first `302` response. *** ## What changed Previously, some API responses returned direct storage URLs such as: ```text theme={null} https://sacra-pdfs.s3.us-east-2.amazonaws.com/spacex.pdf ``` Those fields now return a stable Sacra URL: ```text theme={null} https://sacra.com/f/UjuDFHb2GHgPNfvAKNf0PeowtFiwLUiX ``` When requested, the stable Sacra URL returns a redirect to a short-lived signed delivery URL: ```text theme={null} GET https://sacra.com/f/UjuDFHb2GHgPNfvAKNf0PeowtFiwLUiX HTTP/1.1 302 Found Location: https://content.sacra.com/d/9Xk3mQ7rLp2vNz8bHt4cWy6sFa1uJd0E?Policy=...&Signature=...&Key-Pair-Id=... ``` Use the stable Sacra URL from the API response. Do not store or hardcode the redirected delivery URL, since it is temporary. *** ## Affected API fields This applies anywhere the API previously returned a direct PDF link for Sacra documents or filings. | Endpoint | Affected response field | | --------------------------------------------------- | ----------------------------------------------------------------------- | | `GET /api/v1/documents/{document_slug}` | `pdf_url` | | `GET /api/v1/documents` | `documents[].link` | | `GET /api/v1/documents?company_domain=...` | `documents[].link` | | `GET /api/v1/companies?company_domain=...` | `company.documents[].link` | | `GET /api/v1/companies?company_slug=...` | `company.documents[].link` | | `GET /api/v1/companies?id=...` | `company.documents[].link` | | `GET /api/v1/companies/{company_slug}` | `company.documents[].link` | | `GET /api/v1/categories/{category_slug}/items` | `items[].meta.pdf_url` for document items | | `GET /api/v1/filings` | `filings[].url` | | `POST /api/v1/filings` | `filings[].url` | | `GET /api/v1/funding-rounds` | `funding_rounds[].citations[].url` | | `GET /api/v1/metrics` | `metrics[].citations.sources[].link` for filing evidence sources | | `POST /api/v1/metrics` | `metrics[].citations.sources[].link` for filing evidence sources | | `GET /api/v1/events?include_citations=true` | `events[].citations.items[].sources[].link` for filing evidence sources | | `POST /api/v1/events` with `include_citations=true` | `events[].citations.items[].sources[].link` for filing evidence sources | Most document and filing response fields will use stable `/f/...` Sacra URLs. Some filing evidence citation links may use Sacra filing access URLs such as `/access-filing/filing/{id}`. In both cases, the important behavior is the same: clients should treat the Sacra URL as the stable link and follow redirects to retrieve the PDF bytes. *** ## Example response changes ### Document detail ```json theme={null} // Before { "slug": "spacex", "title": "SpaceX One-Pager", "pdf_url": "https://sacra-pdfs.s3.us-east-2.amazonaws.com/spacex.pdf" } ``` ```json theme={null} // After { "slug": "spacex", "title": "SpaceX One-Pager", "pdf_url": "https://sacra.com/f/UjuDFHb2GHgPNfvAKNf0PeowtFiwLUiX" } ``` ### Documents list ```json theme={null} // Before { "documents": [ { "slug": "spacex", "link": "https://sacra-pdfs.s3.us-east-2.amazonaws.com/spacex.pdf" } ] } ``` ```json theme={null} // After { "documents": [ { "slug": "spacex", "link": "https://sacra.com/f/UjuDFHb2GHgPNfvAKNf0PeowtFiwLUiX" } ] } ``` *** ## Downloading PDFs directly Many HTTP clients follow redirects automatically for `GET` requests. Some clients, command-line calls, and custom downloaders do not. If your code expects the first response from the file URL to be `200 OK` with PDF bytes, update it to allow redirects. ### curl Broken: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ -o spacex.pdf \ "https://sacra.com/f/UjuDFHb2GHgPNfvAKNf0PeowtFiwLUiX" ``` Fixed: ```bash theme={null} curl -L -H "Authorization: Token YOUR_API_KEY" \ -o spacex.pdf \ "https://sacra.com/f/UjuDFHb2GHgPNfvAKNf0PeowtFiwLUiX" ``` The `-L` option tells `curl` to follow redirects. ### Python requests `requests.get()` follows redirects by default, so most Python integrations do not need to change anything. Usually enough: ```python theme={null} import requests response = requests.get( pdf_url, headers={"Authorization": "Token YOUR_API_KEY"}, ) response.raise_for_status() pdf_bytes = response.content ``` Broken only if redirects are disabled: ```python theme={null} import requests response = requests.get( pdf_url, headers={"Authorization": "Token YOUR_API_KEY"}, allow_redirects=False, ) # response.status_code is 302, not the PDF response ``` If your integration or HTTP wrapper disables redirects, remove that override or set `allow_redirects=True`. ### JavaScript fetch Broken if redirects were set to manual: ```javascript theme={null} const response = await fetch(pdfUrl, { headers: { Authorization: "Token YOUR_API_KEY" }, redirect: "manual", }); // response.status is 302, not the PDF response ``` Fixed: ```javascript theme={null} const response = await fetch(pdfUrl, { headers: { Authorization: "Token YOUR_API_KEY" }, redirect: "follow", }); if (!response.ok) { throw new Error(`Failed to fetch PDF: ${response.status}`); } const pdfBytes = await response.arrayBuffer(); ``` The standard `fetch` default is `redirect: "follow"`. The explicit option is useful if your code currently sets `redirect: "manual"` or uses a wrapper that disables redirects. *** ## Notes * The API response field names are unchanged. * The stable Sacra URL is the URL to store, render, or fetch. * The redirected delivery URL is temporary and should not be stored. * Existing direct S3 links will continue to work through **June 14, 2026**, then support for old direct S3 links will be turned off. * Browser-based rendering should continue to work normally. * Backend downloaders should follow redirects when fetching Sacra PDF and filing links. # Companies - Core concepts Source: https://docs.sacra.com/concepts/companies How Sacra defines, identifies, and covers private technology companies A **company** is the core entity in Sacra. Everything else — [documents](/concepts/documents), [metrics](/concepts/revenue), [events](/concepts/events), [news](/concepts/news), filings — is associated with a company. Each company represents a single operating business, identified primarily by its domain, and carries a profile that includes its description, founding year, headquarters, key people, financials, and Sacra's original research on it. ## Coverage universe Sacra covers growth-stage and pre-IPO technology companies — the roughly 500–1,000 private companies that matter most to investors, analysts, and builders tracking the private markets. This is a deliberate contrast with platforms like PitchBook or Crunchbase, which index 3 million or more companies. Sacra's value is depth, not breadth: for every company in our coverage universe, we produce original research, revenue estimates, valuation models, and curated news — rather than aggregating whatever public information is available. If you're building on Sacra, you're working with a curated set of high-signal companies, not a raw directory. ## How companies are identified Sacra uses several identifiers for companies, which appear across API responses: | Field | Type | Description | | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------- | | `domain` | string | The company's primary website domain (e.g. `stripe.com`). This is the **primary identifier** used across the Sacra API. | | `slug` | string | Sacra's unique short-name identifier for the company (e.g. `stripe`). Human-readable, URL-safe, and stable. | | `id` | integer | Sacra's internal numeric ID. Stable and unique, but prefer `domain` or `slug` for readability. | | `cik` | string | SEC Central Index Key, where available. Present for companies that have filed with the SEC. | **Domain is the recommended way to look up and reference companies.** Most API endpoints accept `company_domain` as a query parameter, and it's the most portable identifier across integrations. To retrieve one full company detail payload, use the [company detail endpoint](/api-reference/companies/get-a-company-detail). It accepts a domain, numeric ID, or slug. The list endpoint also carries these query parameters for compatibility, but they return a single `company` object rather than filtering a `companies` array. ## Company entity fields A full company object from the detail endpoint includes: * **Identity** — `id`, `slug`, `name`, `domain`, `type` (`private` or `public`), `is_active` * **Profile** — `description`, `founding_year`, `headquarters` (city and country), `logo` * **People** — `key_people` with `founders` and `ceo` arrays * **Structure** — `legal_entities` (name and country of incorporation) * **Categories** — Sacra's internal taxonomy, each with `id`, `name`, and `slug` * **[Financials](/concepts/revenue)** — `financials` array with name/value pairs for revenue, valuation, and funding * **Listings** — exchange listings with venue, ticker, and dates (for companies that have gone public) * **Milestones** — company milestones with type, date, and description. For structured acquisition parties, lifecycle dates, and deal values, use the [acquisitions beta in Events](/concepts/events#acquisitions). * **Social** — links with `url` and `type` (`twitter`, `linkedin`) * **[Documents](/concepts/documents)** — associated Sacra research documents * **[Datasets](/guides/working-with-datasets)** — revenue and metric time-series data via `company_datasets` ## Example Get a company by domain: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/?company_domain=stripe.com" ``` You can also get the same payload by ID or slug. See [Get company detail](/api-reference/companies/get-a-company-detail) for every supported lookup method. Get a company by slug: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/stripe/" ``` ```json theme={null} { "company": { "id": 1, "slug": "stripe", "name": "Stripe", "domain": "stripe.com", "type": "private", "is_active": true, "cik": null, "founding_year": 2010, "headquarters": { "city": "San Francisco", "country": "US" }, "description": "Global payments infrastructure for the internet.", "categories": [ { "id": 4, "name": "Payments", "slug": "payments" } ], "financials": [ { "name": "revenue", "value": "..." }, { "name": "valuation", "value": "..." } ], "key_people": { "founders": [{ "name": "Patrick Collison" }, { "name": "John Collison" }], "ceo": [{ "name": "Patrick Collison" }] } } } ``` Use `domain` when querying the API wherever possible — it's the most stable and human-readable way to reference a company across endpoints. # Documents - Core concepts Source: https://docs.sacra.com/concepts/documents Sacra's research reports on private companies and markets A **document** is a piece of original Sacra research — a report, interview, or market analysis produced by Sacra's analyst team. Documents are the primary way Sacra publishes qualitative insight on private companies, and they're the source of much of the data that flows into the rest of the platform. ## Document types Sacra produces three types of documents: | Type | Description | | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Company** | In-depth reports on individual companies — covering business model, revenue, growth, competitive position, and Sacra's analysis. | | **Interview** | Transcripts and edited conversations with founders, executives, and buyers. Buyer interviews in particular capture how customers experience and evaluate a product. | | **Market** | Research covering a sector, theme, or competitive landscape. Market reports serve as a catch-all for analysis that isn't scoped to a single company. | The `type` field on every document is one of `company`, `interview`, or `market`. ## Company relationships A document can be related to a company in one of two ways: * **`subject`** — the company is the primary focus of the document * **`connected`** — the company is mentioned or analyzed within a document whose primary subject is something else When you fetch documents for a specific company, both subject and connected documents are returned, each with a `relation` field indicating which applies. ## Document content The full document content is available through the [detail endpoint](/api-reference/documents/get-a-document). The body is parsed into structured **sections**, each with a `type`, `title`, and `elements` array. Sections are linked with `prev_section` and `next_section` pointers for sequential navigation, and a `table_of_contents` provides an outline of the full document. Use the document's `slug` to retrieve one document. The slug is available on each item returned by [List documents](/api-reference/documents/list-documents). The API does not currently support direct document lookup by numeric ID or company identifier. Additional metadata includes: * `reading_time` — estimated reading time in minutes * `has_images` — whether the document contains image elements * `pdf_url` — direct link to the PDF on S3 * `web_url` — link to the document page on sacra.com ## Querying documents The documents endpoint supports two modes: **Company query** — pass `company_domain` or `company_id` to get all documents related to a specific company. Returns a flat, unpaginated `documents` list ordered by relevance. These parameters filter the collection; they do not retrieve one document. **Global query** — omit company filters to search across all documents. Requires a `created_at` or `updated_at` date range of 14 days or less, and returns paginated results. Use `updated_at_gte` for incremental syncs — see [Sync Sacra Research & Data](/guides/syncing-data) for a complete polling guide. Documents can be revised after initial publication, so polling by update time ensures you don't miss changes to existing reports. # Events - Core concepts Source: https://docs.sacra.com/concepts/events How Sacra models company milestones, funding rounds, secondary transactions, corporate actions, and acquisitions An **event** is a structured record of something that happened at a company — a funding round, a secondary transaction, a milestone like an IPO, or a corporate action like a stock split. Events are returned newest first and serve as the authoritative timeline of capital activity for every company Sacra covers. ## Replacing the funding rounds endpoint The legacy `/api/v1/funding-rounds/` endpoint covered only one kind of activity. Events supersede it with a unified model that handles the full range of things that matter to investors tracking private companies: | Event type | Examples | | ----------------------- | --------------------------------------------------------- | | `funding_round` | Seed, Series A–N, growth rounds, crowdfunding | | `secondary_transaction` | Tender offers, direct secondary sales | | `company_milestone` | IPOs, incorporations, delistings | | `corporate_action` | Stock splits, reverse splits, recapitalizations | | `acquisition` (beta) | Announced, closed, and cancelled controlling acquisitions | If you're using the funding rounds endpoint today, migrate to [events](/api-reference/events/get-aggregated-events) and filter by `types=funding-round`. You'll get richer data and access to the other event types in the same response. The `/api/v1/funding-rounds/` endpoint is deprecated. It remains available for backward compatibility but will not receive new data or features. ## Event envelope Every event, regardless of type, shares a common envelope: | Field | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `event_id` | Prefixed unique ID — `fr_` for funding rounds, `st_` for secondary transactions, `ca_` for corporate actions, `cm_` for company milestones, `acq_` for acquisitions | | `event_type` | One of `funding_round`, `secondary_transaction`, `corporate_action`, `company_milestone`, `acquisition` (beta) | | `event_subtype` | More specific classification — e.g. `series_a`, `tender_offer`, `ipo`, `stock_split`. Always `null` for acquisitions. | | `event_name` | Human-readable name for the event, suitable for display in timelines | | `event_date` | The primary date of the event. For acquisitions, depends on status and can be `null` when a closing date is unknown. | | `event_status` | `announced`, `closed`, or `cancelled` | | `event_last_updated_at` | Timestamp of the latest event update | | `company` | Company reference with string `id`, `slug`, and nullable `domain`; the acquired company for acquisitions | | `data` | Event-specific payload — shape varies by `event_type` | ## Data payloads by type The `data` field contains fields specific to each event type. **Funding rounds** include `round_type`, `amount_raised`, `valuation`, `announced_date`, `equities` (a list of preferred share classes issued), and `is_extension` — a boolean that identifies whether the round is an extension of a prior close rather than a new series. **Secondary transactions** include `transaction_type` (e.g. `tender_offer`), `transaction_amount`, `valuation`, `price_per_share`, `announced_date`, and `closing_date`. When a transaction is closed but only one date is known, `closing_date` is set equal to `announced_date`. **Company milestones** include `type`, `date`, `label`, `description`, and a nested `data` object. **Corporate actions** include `announced_date` and `effective_date`, which can differ for events such as stock splits. ### Acquisitions Acquisitions include acquired-company and buyer references, lifecycle dates, and separate nullable `enterprise_value` and `equity_value` money objects. See the [Events API reference](/api-reference/events/get-aggregated-events) for the payload and examples. **Acquisitions are excluded by default.** To include them, send `betas=acquisitions` on GET or `"betas": ["acquisitions"]` in the POST JSON body. This beta requires API v1. Without a `types` filter, the flag adds acquisitions to the default event types. To return only acquisitions, also set `types=acquisition` on GET or `"types": "acquisition"` on POST. The `types` filter alone does not enable the beta. ## Citations Events support optional citations via the `include_citations=true` parameter. When enabled, each event includes a `citations` object with the sources backing the event data — article links, headlines, quotes, and publication names. This is useful when you want to surface the provenance of a funding round or transaction to end users. Use `updated_at_gte` for incremental syncs — see [Sync Sacra Research & Data](/guides/syncing-data) for a complete polling guide. Events are updated as new information surfaces — a round announced at one valuation may be revised as SEC filings come in. # News - Core concepts Source: https://docs.sacra.com/concepts/news How Sacra collects, processes, and surfaces news for private companies Sacra aggregates news from across the web and processes it into a clean, company-attributed feed. Raw articles go through three stages before they surface in the API: entity identification, clustering, and summarization. ## Entity identification Private companies don't have tickers. Matching a news article to the right company requires understanding the text — not just looking for an exact string match. Sacra uses AI to read each article and identify which companies are mentioned. This handles the common cases that string matching gets wrong: name variations ("Stripe" vs. "Stripe Inc."), abbreviations, informal references, and articles that discuss a company without ever using its exact registered name. The result is that each news item is reliably attributed to the companies it actually covers, and you can query news by company domain without worrying about whether the source spelled the name correctly. ## Clustering News from different outlets frequently covers the same underlying event — a funding round, a product launch, a leadership change. Without deduplication, a single story can generate dozens of redundant items. Sacra clusters articles that cover the same event into a single news item. Clustering is based on semantic similarity: articles are grouped when they refer to the same facts, even if the wording differs across sources. Each cluster is treated as one news event, regardless of how many outlets picked it up. This means the news feed you get from the API reflects distinct events, not raw article volume. ## AI-generated headlines and summaries Once articles are clustered into an event, Sacra uses AI to write a single headline and summary for the cluster. The headline and summary are generated from the full set of source articles, so they reflect the most complete picture of the event rather than any one outlet's framing. Each news item in the API includes: | Field | Description | | ---------------- | --------------------------------------------------------------------- | | `headline` | Full AI-generated title for the event | | `short_headline` | Condensed version for compact display | | `description` | Short paragraph synthesizing what happened across all source articles | | `release_date` | When the event was first reported | | `articles` | The source articles that were clustered together | Each article in the `articles` array carries its original `headline`, `link`, `date_published`, `publication`, and `thumbnail`. A `publication_score` is also included to indicate source quality, which you can use to sort or filter the underlying sources. The source articles are always available so you can trace any claim back to its origin. ## Filtering news The [news endpoint](/api-reference/news/get-company-news) accepts several filters: * **`company_domain`** — fetch news for a single company by domain (e.g. `stripe.com`) * **`company_domains`** — comma-separated list for up to 200 companies in a single GET request, or up to 1,000 via the [POST batch endpoint](/api-reference/news/get-company-news-batch) * **`news_type`** — `major` (default) returns only significant events; `all` includes minor mentions * **`release_date_start` / `release_date_end`** — filter by when the event was first reported * **`updated_at_gte` / `updated_at_lte`** — filter by when the news item was last updated; recommended for polling workflows where you want only what's changed since your last sync Use `updated_at_gte` for incremental syncs rather than re-fetching by release date — see [Sync Sacra Research & Data](/guides/syncing-data) for a complete polling guide. News items can be updated as new articles are added to a cluster after the initial release. # Revenue - Core concepts Source: https://docs.sacra.com/concepts/revenue How Sacra models and surfaces revenue data for private companies Sacra surfaces revenue data through two distinct but complementary structures: **revenue datasets**, which are Sacra's own revenue models for each company, and **metric observations**, which are individual datapoints cited to published sources. Both are available through the API and serve different use cases. To work with datasets in code, see [Working with Datasets & Revenue Data](/guides/working-with-datasets). ## Revenue datasets A revenue dataset is Sacra's internal revenue model for a company. It represents a complete, normalized time series of revenue — year by year from the company's earliest tracked period through the current month — with no gaps. The purpose of the dataset is to give you a single clean series you can plot, compare, or sync without needing to reconcile inconsistent data from multiple sources. Sacra fills gaps using its own estimates, clearly distinguished from observed figures. ### Structure Each dataset has a `data_type` that determines what the values represent: | Data type | Description | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | **Revenue** | Trailing revenue — total amount generated for the given period. | | **Recurring Revenue** | Annual recurring revenue (ARR) — the contracted subscription value as of the given date, specific to subscription businesses. | | **Run Rate Revenue** | Annualized revenue as of the given date, regardless of business model. | ### Datapoint periods Each datapoint in a dataset has a date that encodes its period type: * **December 31** — a full year-end figure for that calendar year. * **Any other month-end** — a year-to-date figure through that month. A revenue value dated `2024-04-30` means cumulative revenue from January 2024 through April 2024 — not a trailing 12-month figure. A value dated `2024-12-31` means the full-year total. ```json theme={null} { "x": "2023-12-31T00:00:00.000Z", "y": 170000000, "type": "historical" } { "x": "2024-04-30T00:00:00.000Z", "y": 39600000, "type": "historical" } ``` If the date falls on December 31, treat it as a full-year figure. Any other month-end date is year-to-date. ### How revenue types interact with periods **Revenue** reflects total amounts generated — either for the full year (year-end) or from January 1 through the given month (year-to-date). It does not represent a trailing 12-month window. **Run Rate Revenue** is a forward-looking annualized figure regardless of period type, roughly the most recent month's revenue multiplied by 12. A run rate dated June 2025 implies June 2025 revenue × 12. **Recurring Revenue (ARR)** applies specifically to subscription businesses — it's the annual recurring revenue as of the given date, based on contracted subscription value rather than an annualization of recent revenue. *** ## Metric observations A metric observation is a single revenue or growth datapoint that Sacra has extracted and cited to a specific published source — a news article, earnings call, SEC filing, or industry report from a trusted publication. Where datasets give you a complete modeled series, observations give you the raw evidence behind specific claims. Each observation is precise, sourced, and structured for programmatic use. ### Structure Each observation has a `metric_definition` describing what is being measured and a `measurement` carrying the numeric claim: **`metric_definition`** | Field | Description | | ---------------------- | -------------------------------------------------------------------------------------------------------------------- | | `base` | Metric family: `trailing_revenue`, `run_rate_revenue`, or `recurring_revenue` | | `view` | `value` — a point value or range; `growth` — a growth rate or multiple | | `base_period` | Granularity of the measured window: `year`, `quarter`, `month`, `ytd`, `custom` | | `base_forward` | Forward anchor for ARR and run rate metrics — typically `year` for annualized framing, `month` for MRR-style framing | | `growth_period` | Comparator cadence for growth rows: `year`, `quarter`, `month`, `ytd`, `custom` | | `growth_period_length` | Number of comparator periods — `1` is standard; values above 1 indicate multi-period windows like 3-year CAGR | **`measurement`** | Field | Description | | ------------------------------------- | -------------------------------------------------------------------------------------------- | | `scenario` | `historical` — observed/realized; `projection` — forecast | | `end_date` | Anchor date for the datapoint | | `custom_start_date` | Explicit start of the primary measured window, when the window is non-standard | | `comparison_window_end_date` | End date of the comparison baseline for growth rows — required when `view` is `growth` | | `comparison_window_custom_start_date` | Custom start of the comparison window, when the baseline is non-standard | | `type` | Numeric shape: `equals`, `greater_than`, `less_than`, or `range` | | `amount` / `low` / `high` | Raw numeric values — no symbols, formatting comes from `unit_kind` | | `unit_kind` | `currency`, `percent`, `multiple`, or `count` | | `scope_name` / `scope_type` | If set, the datapoint refers to a segment rather than the whole company | | `status` | Lifecycle status of the datapoint — the `/metrics` endpoint returns active observations only | ### Numeric shapes | `measurement.type` | Read as | | ------------------ | ------------------------ | | `equals` | Exactly `amount` | | `greater_than` | More than `low` | | `less_than` | Less than `high` | | `range` | Between `low` and `high` | `amount`, `low`, and `high` are raw numeric values with no symbols. Display formatting comes from `unit_kind` (and `currency_code` when `unit_kind` is `currency`) combined with `measurement.type`. ### Citations Every observation includes a `citations` object with the sources backing the claim: * `citations.sources[]` — deduplicated list of source URLs, each with an optional `quote` field containing the extracted text that supports the datapoint * `citations.summary.count` — number of unique sources for this observation `quote: null` does not mean the source is invalid — SEC filing URLs are included by default even without an extracted quote. ### Growth observations Growth rows (`view: "growth"`) require a `comparison_window_end_date` to define the baseline: | Case | `end_date` | `comparison_window_end_date` | | ----------- | ------------ | ---------------------------- | | FY2025 YoY | `2025-12-31` | `2024-12-31` | | Q1 2025 YoY | `2025-03-31` | `2024-03-31` | | Q2 2025 QoQ | `2025-06-30` | `2025-03-31` | For growth rows, `unit_kind: "percent"` means percentage growth (e.g. `55` = 55%) and `unit_kind: "multiple"` means an x-multiple (e.g. `3.7` = 3.7×). ### Common patterns **Forward metrics are point-in-time.** For `run_rate_revenue` and `recurring_revenue`, the datapoint is an anchored forward-looking view as of the given date. `base_forward` carries the annualized or monthly framing; `base_period` is commonly `null` for these. **`growth_period_length` above 1** indicates a multi-period cumulative growth window rather than a single prior period comparison. `growth_period: year` with `growth_period_length: 3` means a 3-year CAGR-style window; `growth_period: month` with `growth_period_length: 6` means a 6-month CMGR-style window. **Scoped datapoints** have both `scope_name` and `scope_type` set, indicating the figure applies to a product line or business segment rather than the whole company. If both are null, the datapoint is company-level. **YTD-vs-YTD growth** (`growth_period: ytd`) compares two year-to-date windows: the current YTD anchored by `end_date` and the prior YTD anchored by `comparison_window_end_date`. ### Field roles at a glance | Field | Role | What it is not | | ---------------------------------------- | -------------------------------------------------- | ----------------------------------------- | | `measurement.end_date` | Anchor/end date of the primary measured window | Not automatically the comparison baseline | | `metric_definition.base_period` | Granularity of the primary measured window | Not the growth comparator cadence | | `metric_definition.growth_period` | Comparator cadence for growth rows | Not the primary metric window granularity | | `measurement.comparison_window_end_date` | Explicit baseline anchor for the comparison window | Not optional for growth rows | ### Null handling | Field | `null` means | | ------------------------------------------------- | ------------------------------------------------------------------------------------ | | `metric_definition.base_forward` | Not stored as a forward-framed metric | | `metric_definition.growth_period` | Not a growth row (`view` is `value`) | | `measurement.custom_start_date` | No explicit custom window start | | `measurement.comparison_window_end_date` | For value rows: not applicable. For growth rows: unexpected — this field is required | | `measurement.comparison_window_custom_start_date` | Comparison window is not custom | | `measurement.scope_name` / `scope_type` | Unscoped — datapoint applies to the whole company | | `citations.sources[].quote` | No extracted quote available — the source URL may still be valid evidence | # Tasks & usage billing - Getting started Source: https://docs.sacra.com/concepts/usage How tasks are counted, what's included in each plan, and how overages work Every API request and [MCP tool call](/mcp-overview) consumes **tasks** — the unit Sacra uses to meter usage across all plan tiers. Each plan includes an allocation of tasks, and usage beyond that allocation is billed as overages up to a defined maximum. ## What is a task? A task is consumed each time you query a company. Requests that touch a single company consume 1 task. Requests that query multiple companies at once (such as a batch news or events call) consume 1 task per company queried, with a minimum of 1 task per request. A `/news` request for 5 companies at once consumes 5 tasks. **Agent and MCP usage** follow the same model: tasks are consumed for initiating a request, executing MCP tool calls, and querying companies. Agents often perform multiple tool calls and company lookups in order to complete a single request, so more complex workflows will consume more tasks than simple requests. Tasks are shared across all Sacra products and interfaces, including the Sacra web application, API, MCP integrations, and Sacra Agent. This includes both programmatic usage and end-user activity. ## Tasks by plan | Plan | Included tasks | Max overage tasks | Max total tasks | Max overage charge | | -------- | -------------- | ----------------- | --------------- | ------------------ | | Standard | 500 | 1,000 | 1,500 | \$50 | | Pro | 3,500 | 7,000 | 10,500 | \$350 | | Platform | 25,000 | 50,000 | 75,000 | \$2,500 | For a full breakdown of what's included in each plan, see [Pricing](https://sacra.com/pricing). ## Overages After exhausting your included tasks, requests continue at **\$0.05 per additional task**. Overages accumulate until either your task limit or your charge limit is reached — whichever comes first. Once you reach your task limit, requests will be blocked until the next billing cycle. Once you reach your charge limit, overage charges stop accruing but you can continue making requests until you reach your task limit. For most customers the task limit is reached before the charge limit. The charge limit is primarily relevant to Platform customers with custom high-volume task allocations. # Building with LLMs & AI agents - Guides Source: https://docs.sacra.com/guides/building-with-llms Connect Sacra's MCP server to Claude, ChatGPT, or your own agent and walk through how tools chain together to answer real questions Sacra's [MCP server](/mcp-overview) lets AI agents call Sacra tools directly inside a conversation. This guide walks through connecting to the server, understanding the available tools, and seeing how an agent chains them together to answer a real question like "What's Kraken's latest revenue?" ## Connect to Sacra MCP There are three ways to connect. Pick whichever fits your setup — the tools and data are the same regardless of client. ### Claude 1. Open the official [Sacra connector in the Claude directory](https://claude.ai/directory/connectors/sacra) and click **Connect**. 2. Sign in to Sacra and accept permissions. ### ChatGPT 1. Open the official [Sacra app in ChatGPT](https://chatgpt.com/plugins/plugin_asdk_app_6994e1a4aa408191846109195ecfa307) and add it to your account. 2. Sign in to Sacra and click **Allow**. ### Server-side (any agent SDK) Connect from your own backend with a Sacra API key. This example uses the OpenAI Agents SDK, but any SDK that supports Streamable HTTP MCP works. ```ts theme={null} import { MCPServerStreamableHttp } from "@openai/agents"; const mcpServer = new MCPServerStreamableHttp({ name: "sacra_research_tools", url: "https://mcp.sacra.com/mcp", requestInit: { headers: { Authorization: `Token ${process.env.SACRA_API_KEY}`, }, }, }); ``` Create an API key in your [Organization Settings](https://sacra.com/orgs/settings/general/). See the [server-side MCP page](/mcp-server-side) for a full working example. Never expose your API key in client-side code. For server-side integrations, store it in a secure environment variable or secret manager. *** ## Available tools The MCP server exposes eight tools: | Tool | Description | Key parameters | | -------------------------------- | ------------------------------------------------------------------ | --------------------- | | `search` | Full-text search across Sacra's documents and companies | `query` | | `get_all_company_domains` | Returns every company Sacra tracks with their domains | — | | `get_company_profile` | Fetches a company's full profile (financials, datasets, documents) | `company_domain` | | `get_revenue_signals` | Citation-backed revenue metrics from Sacra Signals Revenue | `company_domain` | | `get_funding_rounds_for_company` | Lists funding rounds for a company | `company_domain` | | `get_news_for_company` | Recent news items about a company | `company_domain` | | `get_document_content` | Returns the full text of a Sacra document | `document_slug_or_id` | | `get_category_items` | Returns related companies and documents for a category | `category_slug` | Most workflows start with `search` or `get_all_company_domains` to find the right entity, then drill in with `get_company_profile`, `get_revenue_signals`, or `get_funding_rounds_for_company` depending on what you need. *** ## Walkthrough: "What's Kraken's latest revenue?" Here's what happens when you ask this question in Claude, ChatGPT, or through a programmatic agent. The tool chain is the same regardless of client — only the UI around it differs. ### Step 1: The agent resolves the company The agent needs to find Kraken in Sacra's database. It calls `get_company_profile`: ```json theme={null} { "tool": "get_company_profile", "parameters": { "company_domain": "kraken.com" } } ``` This returns the full company object including `financials`, `company_datasets`, `documents`, and metadata. The `financials` array contains headline numbers: ```json theme={null} { "financials": [ { "name": "latest_estimated_revenue", "value": 2204000000, "date": "2025-12-31" }, { "name": "latest_estimated_valuation", "value": 20000000000, "date": "2025-11-19" }, { "name": "total_estimated_funding", "value": 832000000, "date": "2025-11-19" } ] } ``` For a simple "latest revenue" question, the agent can answer directly from `financials`: **\$2.2B as of year-end 2025**. ### Step 2 (optional): The agent gets more detail If you ask a follow-up like "How has that changed over time?" or if the agent wants to provide more context, it already has the `company_datasets` array from the same profile response. The revenue dataset gives the full time series: ```json theme={null} { "data_type": "Revenue", "data": [ { "x": "2022-12-31T00:00:00.000Z", "y": 1010000000, "type": "historical" }, { "x": "2023-12-31T00:00:00.000Z", "y": 696300000, "type": "historical" }, { "x": "2024-12-31T00:00:00.000Z", "y": 1658800000, "type": "historical" }, { "x": "2025-12-31T00:00:00.000Z", "y": 2204000000, "type": "historical" } ] } ``` The agent can now plot the change from $1.01B in 2022 to $2.2B in 2025. Kraken revenue time series from 2022 to 2025 ### Step 3 (optional): The agent gets citation-backed metrics If you want sourced data, the agent calls `get_revenue_signals`: ```json theme={null} { "tool": "get_revenue_signals", "parameters": { "company_domain": "kraken.com" } } ``` This returns granular metric observations with citations — URLs and quotes backing each revenue figure. The agent can include these in its response so you know exactly where each number comes from. The agent decides which tools to call based on your question. A simple "What's the revenue?" may only need `get_company_profile`. Asking "What's the sourced revenue with citations?" will trigger `get_revenue_signals` as well. *** ## Walkthrough: "Write me a brief on Kraken" A broader question like this triggers a multi-tool chain. Here's a typical sequence: ### 1. Company profile ```json theme={null} { "tool": "get_company_profile", "parameters": { "company_domain": "kraken.com" } } ``` The agent gets the full profile: description, founding year, key people, headquarters, financials, datasets, categories, and a list of Sacra documents about Kraken. ### 2. Funding rounds ```json theme={null} { "tool": "get_funding_rounds_for_company", "parameters": { "company_domain": "kraken.com" } } ``` Returns each round with dates, amounts raised, valuations, and round types — Seed in 2013, Series A in 2014, through to the Series C and Growth rounds in 2025. ### 3. Recent news ```json theme={null} { "tool": "get_news_for_company", "parameters": { "company_domain": "kraken.com" } } ``` Returns recent news items so the brief includes current developments. ### 4. Deep-dive into a document The company profile includes a `documents` array. If the agent spots a relevant report — say "Kraken at \$1.5B up 128% YoY" — it can pull the full text: ```json theme={null} { "tool": "get_document_content", "parameters": { "slug": "kraken-at-1-5b-up-128-yoy" } } ``` This gives the agent detailed analysis to draw from when writing the brief. ### The result The agent composes all four tool responses into a structured brief: business overview, key people, funding history, revenue trajectory, recent developments, and an investor takeaway — all grounded in Sacra data. *** ## Tips for effective prompting ### Activating the connector In **ChatGPT**, say "Use Sacra" to ensure ChatGPT routes your question through the Sacra connector. In **Claude**, the connector activates automatically when your question matches the tool descriptions, but you can say "Use the Sacra MCP" to be explicit. ### Be specific about what you want The more specific your question, the more targeted the tool chain: | Prompt | Tools the agent typically calls | | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | "What's Kraken's revenue?" | `get_company_profile` | | "What's Kraken's revenue with sources?" | `get_company_profile` → `get_revenue_signals` | | "Write a brief on Kraken" | `get_company_profile` → `get_funding_rounds_for_company` → `get_news_for_company` → `get_document_content` | | "What crypto exchanges does Sacra cover?" | `get_category_items` with `crypto-exchange` | | "Find companies related to stablecoins" | `search` | ### Chain follow-up questions After an initial question, the agent retains context. You can follow up naturally: * "Now compare that to Coinbase" * "What funding rounds led to that valuation?" * "Pull the full report on their revenue growth" Each follow-up triggers additional tool calls without needing to re-fetch earlier data. ### Ask for sources If you want to know where a number comes from, ask explicitly: "What's Kraken's revenue and where does that number come from?" This prompts the agent to call `get_revenue_signals` for citation-backed data. *** ## Next steps * **Build your own charts** from the dataset data: [Working with datasets & revenue data](/guides/working-with-datasets) * **Build a programmatic agent** with the OpenAI Agents SDK: [Server-side Agents / SDKs](/mcp-server-side) * **Explore the full API** for direct endpoint access: [API Reference](/api-reference) # Display company data on your site - Guides Source: https://docs.sacra.com/guides/display-company-data Embed Sacra company data, valuation charts, and research documents into your application The Sacra API provides two ways to display company data on your site: **ready-to-use embeds** that return drop-in HTML iframes, and **raw JSON endpoints** for building fully custom UIs. ## Embeds Embed endpoints return an `embed_html` string containing a styled `" } } ``` Drop the HTML into your page: ```html theme={null}
``` Pass `height` and `width` query parameters to control the iframe dimensions, e.g. `?company_domain=stripe.com&height=600&width=800`. ### Valuation chart An interactive chart showing a company's valuation history. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/embed/company-data-valuation-chart/?company_domain=stripe.com" ``` ### Valuation table A tabular view of valuation data points. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/embed/company-data-valuation-table/?company_domain=stripe.com" ``` ### Document PDF Embed a Sacra research document as a PDF viewer. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/embed/document-pdfs/?document_slug=stripe-revenue" ``` All embed endpoints identify companies by **one of** `company_slug`, `company_domain`, or `company_id`. The document PDF embed uses `document_slug` instead. *** ## Build a custom UI with JSON data If you need full control over presentation, use the JSON endpoints to fetch raw data and render it yourself. ### Fetch company profile The `/api/v1/companies/` endpoint returns the full [company profile](/concepts/companies) including financials, milestones, and metadata. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/?company_domain=stripe.com" ``` The response wraps the company object inside a `company` key: ```json theme={null} { "company": { "id": 112, "slug": "stripe", "name": "Stripe", "domain": "stripe.com", "is_active": true, "type": "private", "logo": { ... }, "social": [ { "url": "https://twitter.com/stripe", "type": "twitter" } ], "founding_year": 2010, "headquarters": { ... }, "description": "...", "financials": [ { "name": "latest_estimated_revenue", "value": 6900000000, "date": "2025-12-30" }, { "name": "latest_estimated_valuation", "value": 91500000000, "date": "2025-02-26" }, { "name": "total_estimated_funding", "value": 9800000000, "date": "2025-05-05" } ], "milestones": [ { "id": "1", "type": "...", "date": "...", "label": "...", "description": "..." } ], "listings": [ { "id": "1", "type": "...", "venue": "...", "ticker": "..." } ], "categories": [ { "id": 12, "name": "fintech", "slug": "fintech" }, { "id": 11, "name": "b2b", "slug": "b2b" } ], "documents": [ ... ], "company_datasets": [ ... ] } } ``` Each entry in `financials` has a snake\_case `name`, a numeric `value`, and a `date`. ### Fetch financial metrics The `/api/v1/metrics/` endpoint returns detailed [metric observations](/concepts/revenue#metric-observations) with citations. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/metrics/?company_domain=stripe.com" ``` You can filter by metric type and date range: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/metrics/?company_domain=stripe.com&metric_base=revenue&measurement_scenario=historical" ``` The response wraps results inside a `metrics` key: ```json theme={null} { "metrics": [ { "metric_id": "35c57075-5f39-46ff-9379-d8408ad3a547", "metric_definition": { "base": "run_rate_revenue", "view": "value", "base_forward": "year", "base_period": null, "growth_period": null, "growth_period_length": null }, "measurement": { "scenario": "historical", "end_date": "2025-01-31", "custom_start_date": null, "comparison_window_end_date": null, "comparison_window_custom_start_date": null, "type": "equals", "unit_kind": "currency", "currency_code": "USD", "amount": 500000000, "low": null, "high": null, "scope_name": null, "scope_type": null, "status": "Active" }, "company": { "id": "112", "slug": "stripe", "domain": "stripe.com" }, "citations": { "summary": { "count": 1 }, "sources": [ { "url": "https://...", "quote": "..." } ] }, "created_at": "2026-02-25T20:17:24.715380+00:00", "updated_at": "2026-02-26T20:27:14.216043+00:00" } ], "pagination": { ... }, "meta": { ... } } ``` Key fields to note: * **`metric_definition.base`** — the metric type (e.g. `revenue`, `run_rate_revenue`, `recurring_revenue`) * **`metric_definition.view`** — either `value` or `growth` * **`measurement.amount`** — the metric value * **`measurement.end_date`** — the date the metric applies to * **`measurement.scenario`** — typically `historical` or `projection` When `metric_definition.view` is `"growth"`, the `amount` field is a percentage — even if `unit_kind` says `"currency"`. Always check the `view` field before interpreting `amount`. Some metrics return `amount: null` with `low` and `high` range values instead of a single point estimate. ### Fetch funding events The `/api/v1/events/` endpoint returns aggregated [company events](/concepts/events) including funding rounds, secondary transactions, milestones, and corporate actions. ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/events/?company_domain=stripe.com&types=funding-round" ``` Filter by event type using the `types` parameter. Supported values: `funding-round`, `secondary-transaction`, `company-milestone`, `corporate-action`. To include `acquisition`, also send `betas=acquisitions` (v1 only). See the [Events API reference](/api-reference/events/get-aggregated-events) for the payload and nullable dates and values. The `types` query parameter uses kebab-case, while the `event_type` field in the response uses snake\_case (e.g. `funding_round`). The response wraps results inside an `events` key: ```json theme={null} { "events": [ { "event_id": "fr_561d3001-52d0-4dfc-b2f2-1b2ed5d9e22a", "event_type": "funding_round", "event_subtype": "series_a", "event_name": "Series A (2026)", "event_date": "2026-02-23", "event_status": "closed", "event_last_updated_at": "2026-02-24T18:05:55.786756+00:00", "company": { "id": "112", "slug": "stripe", "domain": "stripe.com" }, "data": { "id": "561d3001-52d0-4dfc-b2f2-1b2ed5d9e22a", "name": "Series A (2026)", "round_type": "series_a", "amount_raised": "16600000.00", "updated_at": "2026-02-24T18:05:55.786756+00:00" } } ], "pagination": { ... }, "meta": { ... } } ``` Each event has top-level metadata (`event_type`, `event_name`, `event_date`, `event_status`) and a `data` object with type-specific details like `amount_raised` for funding rounds. *** ## Example: React company card Here's a complete example building a company card component with React. The component fetches data through your own backend proxy to keep the API token server-side. ```jsx theme={null} import { useState, useEffect } from "react"; function CompanyCard({ domain }) { const [company, setCompany] = useState(null); useEffect(() => { fetch(`/api/sacra/company?domain=${domain}`) .then((res) => res.json()) .then((data) => setCompany(data.company)); }, [domain]); if (!company) return
Loading...
; const findFinancial = (name) => company.financials?.find((f) => f.name === name); const revenue = findFinancial("latest_estimated_revenue"); const valuation = findFinancial("latest_estimated_valuation"); return (

{company.name}

{company.description}

{revenue && ( <>
Revenue
${(revenue.value / 1e9).toFixed(1)}B
)} {valuation && ( <>
Valuation
${(valuation.value / 1e9).toFixed(1)}B
)}
); } ``` The `/api/sacra/company` route is a backend proxy you create to forward requests to the Sacra API. A minimal Express example: ```js theme={null} app.get("/api/sacra/company", async (req, res) => { const response = await fetch( `https://sacra.com/api/v1/companies/?company_domain=${req.query.domain}`, { headers: { Authorization: `Token ${process.env.SACRA_API_KEY}` } } ); res.json(await response.json()); }); ``` Never expose your API token in client-side code shipped to end users. Proxy requests through your own backend and keep the token server-side. *** ## Embed reference | Endpoint | Method | Identifies by | Returns | | --------------------------------------------- | ------ | ---------------------------------------------- | ---------------------- | | `/api/v1/embed/company-data-summary/` | GET | company\_slug, company\_domain, or company\_id | Summary card iframe | | `/api/v1/embed/company-data-valuation-chart/` | GET | company\_slug, company\_domain, or company\_id | Valuation chart iframe | | `/api/v1/embed/company-data-valuation-table/` | GET | company\_slug, company\_domain, or company\_id | Valuation table iframe | | `/api/v1/embed/document-pdfs/` | GET | document\_slug | PDF viewer iframe | | `/api/v1/embed/charts/` | PUT | dataset\_id (in request body) | Custom chart iframe | # Sync Sacra research & data - Guides Source: https://docs.sacra.com/guides/syncing-data Set up a daily cron job that polls Sacra's documents, news, and events endpoints to keep a local copy up to date The Sacra API supports time-windowed queries across [`/documents`](/concepts/documents), [`/news/company`](/concepts/news), and [`/events`](/concepts/events), so you can poll for changes on a schedule instead of re-fetching everything. This guide walks through setting up a daily sync that fetches only what's changed in the last 24 hours. ## How sync works All three endpoints accept `updated_at_gte` and `updated_at_lte` query parameters to filter results to a time window. Combine these with cursor pagination to walk through all changes since your last sync. | Endpoint | Response key | Pagination | Time filter support | | ---------------------- | -------------- | ------------------------------------ | ------------------------------------------ | | `/api/v1/documents` | `documents` | Cursor (default) | `created_at_gte/lte`, `updated_at_gte/lte` | | `/api/v1/news/company` | `company_news` | Cursor (default) | `created_at_gte/lte`, `updated_at_gte/lte` | | `/api/v1/events` | `events` | Cursor (opt-in: `pagination=cursor`) | `created_at_gte/lte`, `updated_at_gte/lte` | Domain-less news queries (no `company_domain` parameter) require a date window of **14 days or less**. A daily 24-hour window is well within this limit. *** ## Query structure Each sync request uses the same pattern: a 24-hour window on `updated_at` with cursor pagination to handle multiple pages. ### Documents ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/documents?updated_at_gte=2026-04-16T00:00:00Z&updated_at_lte=2026-04-17T00:00:00Z" ``` ### News ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/news/company?updated_at_gte=2026-04-16T00:00:00Z&updated_at_lte=2026-04-17T00:00:00Z" ``` ### Events Events require `pagination=cursor` to use cursor pagination: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/events?pagination=cursor&updated_at_gte=2026-04-16T00:00:00Z&updated_at_lte=2026-04-17T00:00:00Z" ``` *** ## Include acquisition updates Add `betas=acquisitions` to your Events requests to include [acquisitions](/concepts/events#acquisitions). Add `types=acquisition` if you only want that event type. For POST, send `"betas": ["acquisitions"]`. The beta requires API v1. Use update-time filters for incremental acquisition syncs: `start_date` and `end_date` filter the announcement, closing, or cancellation date according to status, and exclude closed deals with an unknown closing date. Upsert on the stable `event_id` as status, dates, and values change. Disabled records disappear from Events; this feed does not emit deletion events. ## Pagination The GET requests in this guide return a `pagination` object with `next_link` when there are more results. Events requires `pagination=cursor` for this shape. Follow `next_link` until it's `null` to fetch all pages. For POST Events requests, prefer `pagination=page` (the default). Increment `page` while `pagination.has_next` is `true`. POST cursor responses always return `next_link` and `prev_link` as `null`; do not interpret those links as completion signals for a batch request. ```json theme={null} { "pagination": { "page_size": 30, "current_page_items": 30, "total_items": 85, "next_link": "https://sacra.com/api/v1/documents?updated_at_gte=...&page_after=abc123", "prev_link": null, "after_cursor": "abc123", "before_cursor": null } } ``` Use the `next_link` URL directly — it includes all your original query parameters plus the cursor. *** ## Complete sync script This Node.js script polls all three endpoints with a 24-hour window and collects every changed record. You can wire the results into your database, search index, or file system. ```js theme={null} const API_BASE = "https://sacra.com/api/v1"; const API_KEY = process.env.SACRA_API_TOKEN; async function fetchAllPages(url) { const results = []; let nextUrl = url; while (nextUrl) { const res = await fetch(nextUrl, { headers: { Authorization: `Token ${API_KEY}` }, }); if (!res.ok) { throw new Error(`${res.status} ${res.statusText}: ${nextUrl}`); } const json = await res.json(); // Each endpoint wraps results in a different key const items = json.documents || json.company_news || json.events || []; results.push(...items); nextUrl = json.pagination?.next_link || null; } return results; } function buildTimeWindow() { const now = new Date(); const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000); // Format as ISO 8601 for the API const gte = yesterday.toISOString(); const lte = now.toISOString(); return { gte, lte }; } async function sync() { const { gte, lte } = buildTimeWindow(); const timeParams = new URLSearchParams({ updated_at_gte: gte, updated_at_lte: lte, }); const eventsParams = new URLSearchParams({ pagination: "cursor", updated_at_gte: gte, updated_at_lte: lte, }); console.log(`Syncing changes from ${gte} to ${lte}`); const [documents, news, events] = await Promise.all([ fetchAllPages(`${API_BASE}/documents?${timeParams.toString()}`), fetchAllPages(`${API_BASE}/news/company?${timeParams.toString()}`), fetchAllPages(`${API_BASE}/events?${eventsParams.toString()}`), ]); console.log( `Fetched ${documents.length} documents, ${news.length} news items, ${events.length} events` ); // Replace this with your storage logic await saveDocuments(documents); await saveNews(news); await saveEvents(events); } // Placeholder functions — replace with your database/storage logic async function saveDocuments(docs) { for (const doc of docs) { console.log(` doc: ${doc.slug} — ${doc.title} (updated ${doc.updated_at})`); // e.g. db.documents.upsert({ id: doc.id, ...doc }) } } async function saveNews(items) { for (const item of items) { console.log(` news: ${item.short_headline} — ${item.company?.domain} (${item.release_date})`); // e.g. db.news.upsert({ id: item.id, ...item }) } } async function saveEvents(events) { for (const event of events) { console.log(` event: ${event.event_name} — ${event.company?.domain} (${event.event_date})`); // e.g. db.events.upsert({ id: event.event_id, ...event }) } } sync().catch((err) => { console.error("Sync failed:", err); process.exit(1); }); ``` Run it manually to verify: ```bash theme={null} SACRA_API_TOKEN=your_key_here node sync.js ``` Expected output: ``` Syncing changes from 2026-04-16T00:00:00.000Z to 2026-04-17T00:00:00.000Z Fetched 3 documents, 12 news items, 5 events doc: kraken — Kraken One-Pager (updated 2026-04-16T19:03:59.691Z) doc: owner — Owner One-Pager (updated 2026-04-16T21:01:20.492Z) ... ``` *** ## Schedule with cron Once the script works, schedule it to run daily. A common choice is once per day at midnight UTC. ### Linux/macOS crontab ```bash theme={null} crontab -e ``` Add: ``` 0 0 * * * SACRA_API_TOKEN=your_key_here /usr/local/bin/node /path/to/sync.js >> /var/log/sacra-sync.log 2>&1 ``` ### GitHub Actions ```yaml theme={null} name: Sacra Sync on: schedule: - cron: "0 0 * * *" # midnight UTC daily workflow_dispatch: # allow manual trigger jobs: sync: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: node sync.js env: SACRA_API_TOKEN: ${{ secrets.SACRA_API_TOKEN }} ``` Store your API key in environment variables or a secret manager. Never hardcode it in the script or commit it to source control. *** ## Tracking sync state The script above uses a rolling 24-hour window, which is simple but may miss items if a sync run is skipped or delayed. For more robust syncing, persist the timestamp of your last successful sync and use that as the `gte` boundary. ```js theme={null} const { readFileSync, writeFileSync } = require("fs"); const STATE_FILE = ".sacra-sync-state.json"; function getDefaultLastSyncTime() { return new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(); } function getLastSyncTime() { try { const state = JSON.parse(readFileSync(STATE_FILE, "utf-8")); const lastSync = state?.last_sync; if (typeof lastSync === "string") { const parsedLastSync = new Date(lastSync); if (!Number.isNaN(parsedLastSync.getTime())) { return parsedLastSync.toISOString(); } } } catch { // Ignore read/parse errors and fall back to a safe default below } // First run or invalid state — default to 24 hours ago return getDefaultLastSyncTime(); } function saveLastSyncTime(timestamp) { writeFileSync(STATE_FILE, JSON.stringify({ last_sync: timestamp })); } async function sync() { const gte = getLastSyncTime(); const lte = new Date().toISOString(); const timeParams = `updated_at_gte=${gte}&updated_at_lte=${lte}`; console.log(`Syncing changes from ${gte} to ${lte}`); const [documents, news, events] = await Promise.all([ fetchAllPages(`${API_BASE}/documents?${timeParams}`), fetchAllPages(`${API_BASE}/news/company?${timeParams}`), fetchAllPages(`${API_BASE}/events?pagination=cursor&${timeParams}`), ]); console.log( `Fetched ${documents.length} documents, ${news.length} news items, ${events.length} events` ); await saveDocuments(documents); await saveNews(news); await saveEvents(events); // Only update the checkpoint after everything succeeds saveLastSyncTime(lte); console.log(`Checkpoint saved: ${lte}`); } ``` This way, if a run fails midway, the next run retries from the same starting point. If you're running on GitHub Actions or a stateless environment, store the checkpoint in your database or an S3 object instead of a local file. *** ## Using `created_at` vs `updated_at` The endpoints support both `created_at` and `updated_at` filters. Which you use depends on what you're trying to capture: | Filter | Catches | Misses | | -------------------- | ----------------------------------------- | ----------------------------------------- | | `updated_at_gte/lte` | New items **and** edits to existing items | Nothing — this is the recommended default | | `created_at_gte/lte` | Only newly created items | Updates to previously synced items | Use `updated_at` for sync workflows. It catches both new and modified records in a single pass. *** ## Scoping to specific companies If you only care about a subset of companies, add `company_domain` to scope results: ```bash theme={null} # Only Kraken documents curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/documents?company_domain=kraken.com&updated_at_gte=2026-04-16T00:00:00Z&updated_at_lte=2026-04-17T00:00:00Z" ``` This works for all three endpoints. Company-scoped queries don't have the 14-day window limit that domain-less news queries have. *** ## Tips * **Upsert, don't insert.** Use `id` (documents, news) or `event_id` (events) as the primary key and upsert on each sync. An item updated twice in 24 hours will appear once in the response with its latest state. * **Overlap your windows slightly.** If you're using a fixed 24-hour window rather than checkpoint-based sync, consider a small overlap (e.g., 25 hours) to avoid missing items updated right at the boundary. * **Handle empty pages.** Some days may have no changes for a given endpoint. The response will have an empty array and `total_items: 0` — this is normal. * **Log what you sync.** The script above logs each synced item. In production, log the counts and any errors so you can audit sync health. * **Rate limiting.** The Sacra API has rate limits. If you're syncing large volumes, add a small delay between paginated requests. For daily syncs with a 24-hour window, you're unlikely to hit limits. * **See the changelog.** For full details on the sync-related API additions, see [Content Synchronization Updates](/changelog/content-sync). # Working with datasets & revenue data - Guides Source: https://docs.sacra.com/guides/working-with-datasets Use company_datasets from the Sacra API to build revenue charts, valuation timelines, and fundraising histories Every company profile returned by `/api/v1/companies/` includes a `company_datasets` array — chart-ready time series data you can plot directly. Each dataset is a named series of `{x, y}` points covering revenue, valuation, fundraising, and share price history. This guide walks through a real response (Kraken) to show how the data is structured and how to turn it into charts. ## When to use `company_datasets` | Use case | Best option | | ----------------------------------------- | -------------------------------------------------------------------------- | | Drop-in chart with no custom UI | [Embed endpoints](/guides/display-company-data#embeds) | | Chart-ready time series for custom charts | `company_datasets` on `/api/v1/companies/` | | Granular metrics with citations | [`/api/v1/metrics/`](/guides/display-company-data#fetch-financial-metrics) | | Funding round details | [`/api/v1/events/`](/guides/display-company-data#fetch-funding-events) | `company_datasets` is the sweet spot when you want to build your own charts without having to aggregate raw metric rows yourself. The data comes pre-aggregated and sorted chronologically. *** ## Fetch company datasets Request Kraken's company profile: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/?company_domain=kraken.com" ``` The `company_datasets` array lives inside the `company` object alongside `financials`, `documents`, and other fields: ```json theme={null} { "company": { "id": 239, "name": "Kraken", "domain": "kraken.com", "financials": [ ... ], "company_datasets": [ { "id": "0fcc2ca9-ba40-4301-95e6-807341de19dc", "name": "Kraken: Revenue ($M)", "data_type": "Revenue", "metric": "USD", "frequency": "Year", "x_label": "Time", "y_label": "Revenue", "data": [ { "x": "2022-12-31T00:00:00.000Z", "y": 1010000000, "type": "historical" }, { "x": "2023-12-31T00:00:00.000Z", "y": 696300000, "type": "historical" }, { "x": "2024-12-31T00:00:00.000Z", "y": 1658800000, "type": "historical" }, { "x": "2025-12-31T00:00:00.000Z", "y": 2204000000, "type": "historical" } ], "source_type": "Google Sheets", "start_date": "2022-12-31T00:00:00Z", "end_date": "2025-12-31T00:00:00Z" }, ... ] } } ``` A single company can have multiple datasets spanning different data types. *** ## Dataset object reference Each object in `company_datasets` has these fields: | Field | Type | Description | | ------------- | ------ | --------------------------------------------------------------------- | | `id` | string | Unique dataset identifier (UUID) | | `name` | string | Human-readable label, e.g. `"Kraken: Revenue ($M)"` | | `data_type` | string | What the dataset measures (see [dataset types](#dataset-types) below) | | `metric` | string | Unit — `"USD"` or `"Percent"` | | `frequency` | string | Granularity — `"Year"` or `"Month"` | | `x_label` | string | Suggested x-axis label | | `y_label` | string | Suggested y-axis label | | `data` | array | Array of data points (see below) | | `source_type` | string | Data provenance — `"Google Sheets"`, `"Filing"`, `"AI Search"` | | `source_url` | string | Link to the underlying source | | `start_date` | string | Earliest data point date | | `end_date` | string | Latest data point date | | `status` | string | `"Active"` for live datasets | | `created_at` | string | When the dataset was first created | | `updated_at` | string | When the dataset was last modified | | `company` | number | Company ID | ### Data points Each entry in the `data` array has this shape: ```json theme={null} { "x": "2024-12-31T00:00:00.000Z", "y": 1658800000, "type": "historical", "meta": { ... } } ``` | Field | Type | Description | | ------ | -------------- | ------------------------------------------------- | | `x` | string | ISO 8601 timestamp — the date for this data point | | `y` | number | The value — raw numeric, no pre-formatting | | `type` | string | `"historical"` for observed data | | `meta` | object \| null | Optional metadata that varies by dataset type | `y` values are always raw numbers. Revenue of $1.66B is returned as `1658800000`, not `1658.8` or `"$1.66B"\`. Format values for display in your UI. Date conventions for revenue data points follow the same rules described in the [Revenue concepts page](/concepts/revenue#datapoint-periods): December 31 dates are full-year figures, any other month-end date is year-to-date. *** ## Dataset types Here are the dataset types you'll find in `company_datasets`, illustrated with Kraken's data: ### Revenue Annual or year-to-date revenue figures in USD. ```json theme={null} { "data_type": "Revenue", "metric": "USD", "data": [ { "x": "2022-12-31T00:00:00.000Z", "y": 1010000000, "type": "historical" }, { "x": "2023-12-31T00:00:00.000Z", "y": 696300000, "type": "historical" }, { "x": "2024-12-31T00:00:00.000Z", "y": 1658800000, "type": "historical" }, { "x": "2025-12-31T00:00:00.000Z", "y": 2204000000, "type": "historical" } ] } ``` ### Revenue Growth Rate Year-over-year revenue growth as a decimal. A value of `1.38` means 138% growth, `-0.28` means a 28% decline. ```json theme={null} { "data_type": "Revenue Growth Rate", "metric": "Percent", "data": [ { "x": "2023-12-31T00:00:00.000Z", "y": -0.2796, "type": "historical" }, { "x": "2024-12-31T00:00:00.000Z", "y": 1.3823, "type": "historical" }, { "x": "2025-12-31T00:00:00.000Z", "y": 0.3287, "type": "historical" } ] } ``` Growth rates are decimals, not percentages. Multiply by 100 for display: `(y * 100).toFixed(1) + "%"`. ### Valuation Company valuation at each funding event. The `meta` object identifies the specific round. ```json theme={null} { "data_type": "Valuation", "metric": "USD", "data": [ { "x": "2019-06-25T00:00:00.000Z", "y": 4000000000, "type": "historical", "meta": { "name": "Growth 2019", "status": "closed", "event_id": "fr_ded4bbd8-86e5-4748-afa7-5cde4961a91a", "event_type": "funding_round", "event_subtype": "growth" } }, { "x": "2025-07-29T00:00:00.000Z", "y": 15000000000, "type": "historical", "meta": { "name": "Series C 2025", "status": "closed", "event_id": "fr_982c6a4f-6d6b-4a1e-97c8-53351cf67ccb", "event_type": "funding_round", "event_subtype": "series_c" } } ] } ``` ### Amount Raised Total capital raised per year, aggregated across all rounds in that year. The `meta` object includes the aggregation method and number of events. ```json theme={null} { "data_type": "Amount Raised", "metric": "USD", "data": [ { "x": "2014-12-31T00:00:00.000Z", "y": 5000000, "type": "historical", "meta": { "year": 2014, "aggregation": "annual_sum", "event_count": 1 } }, { "x": "2025-12-31T00:00:00.000Z", "y": 1000000000, "type": "historical", "meta": { "year": 2025, "aggregation": "annual_sum", "event_count": 2 } } ] } ``` ### Price per Share Share price at each funding round. The `meta` object links back to the specific event. ```json theme={null} { "data_type": "Price per Share", "metric": "USD", "data": [ { "x": "2013-01-31T00:00:00.000Z", "y": 0.03, "type": "historical", "meta": { "name": "Seed 2013", "event_subtype": "seed" } }, { "x": "2025-09-25T00:00:00.000Z", "y": 61.47, "type": "historical", "meta": { "name": "Growth (2025)", "event_subtype": "growth" } } ] } ``` ### Issue Price Similar to Price per Share but sourced from filings. May contain the same values with different provenance. ```json theme={null} { "data_type": "Issue Price", "metric": "USD", "data": [ { "x": "2013-01-31T00:00:00.000Z", "y": 0.03, "type": "historical" }, { "x": "2025-11-21T00:00:00.000Z", "y": 61.47, "type": "historical" } ] } ``` *** ## Filtering datasets by type To find a specific dataset, filter the array by `data_type`: ```js theme={null} const datasets = company.company_datasets; const revenue = datasets.find(d => d.data_type === "Revenue"); const growth = datasets.find(d => d.data_type === "Revenue Growth Rate"); const valuation = datasets.find(d => d.data_type === "Valuation"); const raised = datasets.find(d => d.data_type === "Amount Raised"); const sharePrice = datasets.find(d => d.data_type === "Price per Share"); ``` Not every company will have every dataset type. Always check that the dataset exists before accessing its data. *** ## Example: revenue chart This React component fetches a company and renders a revenue bar chart using [Recharts](https://recharts.org/). ```jsx theme={null} import { useState, useEffect } from "react"; import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } from "recharts"; function RevenueChart({ domain }) { const [chartData, setChartData] = useState(null); useEffect(() => { fetch(`/api/sacra/company?domain=${domain}`) .then((res) => res.json()) .then(({ company }) => { const dataset = company.company_datasets.find( (d) => d.data_type === "Revenue" ); if (!dataset) return; setChartData( dataset.data.map((point) => ({ year: new Date(point.x).getFullYear(), revenue: point.y, })) ); }); }, [domain]); if (!chartData) return
Loading...
; const formatUSD = (value) => `$${(value / 1e9).toFixed(1)}B`; return ( formatUSD(value)} /> ); } ``` This renders a bar chart showing Kraken's annual revenue from 2022 through 2025, with values formatted as billions. *** ## Example: valuation timeline Valuation datasets include `meta` with the funding round name, which you can use as data point labels. ```jsx theme={null} import { useState, useEffect } from "react"; import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, LabelList, } from "recharts"; function ValuationTimeline({ domain }) { const [chartData, setChartData] = useState(null); useEffect(() => { fetch(`/api/sacra/company?domain=${domain}`) .then((res) => res.json()) .then(({ company }) => { const dataset = company.company_datasets.find( (d) => d.data_type === "Valuation" ); if (!dataset) return; setChartData( dataset.data.map((point) => ({ date: new Date(point.x).toLocaleDateString("en-US", { year: "numeric", month: "short", }), valuation: point.y, label: point.meta?.name || "", })) ); }); }, [domain]); if (!chartData) return
Loading...
; const formatUSD = (value) => `$${(value / 1e9).toFixed(0)}B`; return ( formatUSD(value)} /> ); } ``` For Kraken, this plots two points: Growth 2019 ($4B) and Series C 2025 ($15B), each labeled with the round name from `meta`. *** ## Example: fundraising history table For fundraising data, a table is often more useful than a chart since the Amount Raised dataset is aggregated annually while Price per Share is per-round. ```jsx theme={null} function FundraisingHistory({ company }) { const raised = company.company_datasets.find( (d) => d.data_type === "Amount Raised" ); const sharePrice = company.company_datasets.find( (d) => d.data_type === "Price per Share" ); const formatUSD = (value) => { if (value >= 1e9) return `$${(value / 1e9).toFixed(1)}B`; if (value >= 1e6) return `$${(value / 1e6).toFixed(1)}M`; return `$${value.toFixed(2)}`; }; return (
{raised && ( {raised.data.map((point) => ( ))}
Year Amount Raised Rounds
{point.meta?.year ?? new Date(point.x).getFullYear()} {formatUSD(point.y)} {point.meta?.event_count ?? "—"}
)} {sharePrice && ( {sharePrice.data.map((point) => ( ))}
Date Round Price per Share
{new Date(point.x).toLocaleDateString("en-US", { year: "numeric", month: "short", })} {point.meta?.name || "—"} {formatUSD(point.y)}
)}
); } ``` For Kraken, the share price table shows the progression from $0.03 at Seed (2013) to $61.47 at the Growth round (2025) — a \~2,000x increase. *** ## Tips * **Values are raw numbers.** Revenue of \$2.2B is returned as `2204000000`. Always format for display. * **Growth rates are decimals.** A `y` of `1.38` on a Revenue Growth Rate dataset means 138% growth. Multiply by 100 for percentage display. * **Not every company has every dataset type.** Always check that `find()` returns a result before accessing `.data`. * **Date conventions matter.** December 31 dates are full-year figures; other month-end dates are year-to-date. See the [Revenue concepts page](/concepts/revenue#datapoint-periods) for details. * **`meta` varies by dataset type.** Valuation and Price per Share datasets include funding round details (`name`, `event_subtype`, `event_id`). Amount Raised includes aggregation info (`year`, `event_count`). Revenue datasets typically have no `meta`. * **Use `/events/` for richer funding data.** If you need investor names, round details, or secondary transactions beyond what `meta` provides, query the [`/api/v1/events/`](/guides/display-company-data#fetch-funding-events) endpoint. * **Use `/metrics/` for citations.** Datasets don't include citation sources. If you need to show where a revenue figure came from, use [`/api/v1/metrics/`](/guides/display-company-data#fetch-financial-metrics) which returns full citation chains. # Introduction - Getting started Source: https://docs.sacra.com/index Integrate Sacra's private company research and data into your application Sacra is a research and data platform covering growth-stage and pre-IPO companies. We produce original research — company reports, analyst interviews, revenue models, and curated news — on the private companies that matter most to investors and builders. The API makes all of it programmatically accessible: revenue estimates, valuations, funding rounds, research documents, and news. It's used to power marketplaces, investing apps, wealth management platforms, and research tools. Get your API key and make your first request in minutes. ## Go further Full endpoint reference with parameters, response schemas, and examples. Connect Sacra directly to Claude, ChatGPT, Cursor, or your own agent — no API calls required. # Integrations via MCP - MCP Source: https://docs.sacra.com/mcp-anywhere Use Sacra's MCP server in any platform that supports the Model Context Protocol Sacra's MCP server runs over Streamable HTTP at `https://mcp.sacra.com/mcp` — the same standard that Claude, ChatGPT, Cursor, and a growing number of AI platforms use to connect external tools. If a product supports custom MCP servers, you can connect Sacra to it. For a product overview, see [Sacra MCP](https://sacra.com/features/mcp). Two things you'll need regardless of platform: * **MCP server URL:** `https://mcp.sacra.com/mcp` * **Authentication:** OAuth (preferred, where supported) or a Sacra API key from your [Organization Settings](https://sacra.com/orgs/settings/general/) *** ## Intercom Fin [Fin](https://fin.ai) is Intercom's AI support agent. With Sacra connected, Fin can answer questions about private companies using live Sacra data — useful for sales support bots, investor portals, or any customer-facing experience where your users ask about growth-stage companies. Custom MCP is currently only supported for US-hosted Intercom workspaces. EU and AU workspaces are not yet supported. ### Setup 1. In Intercom, go to **Settings → Data connectors**. 2. Click the **Custom MCP** tile. 3. Fill in the connection details: * **Name:** `Sacra Private Markets Research` * **URL:** `https://mcp.sacra.com/mcp` * **Authentication:** Click **Add token** and paste your Sacra API key 4. Click **Add MCP Server**. 5. Once added, check **"Enable Fin to use this connector directly"** so Fin automatically reaches for Sacra tools when a conversation calls for it — no manual workflow wiring required. ### What Fin can do with Sacra Once connected, Fin has access to the full Sacra MCP tool set. You can instruct it via your Fin system prompt, for example: > When a user asks about a private company's revenue, funding history, or investors, use the Sacra MCP tools to look up the company and answer based on Sacra data. Fin will call tools like `get_company_profile`, `get_funding_rounds_for_company`, and `get_news_for_company` automatically when relevant, and ground its response in Sacra's data. *** ## Cursor (vibe coding) [Cursor](https://cursor.com) supports MCP natively, which means you can give your AI coding assistant live access to Sacra company data while you build. This is useful when building financial tools, investor dashboards, or anything that involves reasoning about private companies — instead of pasting in context manually, your AI just calls Sacra directly. ### Setup Add Sacra to your Cursor MCP config at `~/.cursor/mcp.json`: ```json theme={null} { "mcpServers": { "sacra": { "url": "https://mcp.sacra.com/mcp", "headers": { "Authorization": "Token YOUR_API_KEY" } } } } ``` Restart Cursor after saving. You'll see Sacra listed as an available MCP tool in the model context panel. ### What you can do With Sacra connected in Cursor, you can prompt your AI directly while coding: > Use Sacra to pull the company profile and latest funding rounds for ramp.com, then scaffold a React component that displays the data. The AI will call Sacra's MCP tools, receive the live data, and use it to generate code grounded in real company information — no copy-pasting from the browser. *** ## Other MCP-compatible platforms The same pattern applies anywhere that accepts a custom MCP server URL: | Platform | Where to add | | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | [Claude](/mcp-client#claude-connector-for-sacra) | Official connector in the [Claude directory](https://claude.ai/directory/connectors/sacra) | | [ChatGPT](/mcp-client#chatgpt-app-for-sacra) | Official app in the [ChatGPT app directory](https://chatgpt.com/plugins/plugin_asdk_app_6994e1a4aa408191846109195ecfa307) | | Cursor | `~/.cursor/mcp.json` | | Windsurf | Settings → MCP servers | | Zed | `~/.config/zed/settings.json` under `context_servers` | | Any MCP host | Use `https://mcp.sacra.com/mcp` + your Sacra API key | If the platform supports OAuth, use it — it's simpler than managing API keys. If it only supports token auth, use your Sacra API key from [Organization Settings](https://sacra.com/orgs/settings/general/). # ChatGPT & Claude clients - MCP Source: https://docs.sacra.com/mcp-client Connect Sacra to ChatGPT or Claude with the official app and connector — one click, no API key required Sacra is available as an official app in ChatGPT and an official connector in Claude. Install from the directory, sign in to Sacra, and both apps can pull company profiles, funding history, revenue signals, recent news, and analyst write-ups directly into a conversation. No API key, custom configuration, or developer mode required. See [Sacra MCP](https://sacra.com/features/mcp) for a full product overview. ## ChatGPT App for Sacra The official Sacra app for ChatGPT lets you pull private company data directly into ChatGPT conversations using the Model Context Protocol. Setup takes under a minute and only requires a Sacra account. 1. **Add the Sacra app:** Go to the [Sacra app in ChatGPT](https://chatgpt.com/plugins/plugin_asdk_app_6994e1a4aa408191846109195ecfa307) — or search for "Sacra" in ChatGPT's app directory — and click to add it to your ChatGPT account. 2. **Sign in and allow access:** You'll be redirected to the Sacra sign-in screen. Log in and click "Allow". Sacra only reads data and never modifies or deletes your data. 3. **Use Sacra in chat:** Say "Use Sacra" when you want Sacra data. ChatGPT will request tool permissions; approve and continue. Once connected, try prompts like "Use Sacra to give me an overview of Rippling" or "Use Sacra to compare the funding history of Databricks and Snowflake." ChatGPT will call the relevant Sacra tools automatically and incorporate the results into its response. ## Claude Connector for Sacra The official Sacra connector for Claude adds Sacra as a remote MCP server, giving Claude direct access to Sacra's company data tools. With the connector active, Claude can look up company profiles, funding rounds, recent news, and in-depth research reports on demand — and weave that data into longer-form analysis, memos, or comparisons. 1. **Connect the Sacra connector:** Go to the [Sacra connector in the Claude directory](https://claude.ai/directory/connectors/sacra) — or find it under Settings → Connectors in Claude — and click "Connect". 2. **Sign in and allow access:** You'll be redirected to the Sacra sign-in screen. Log in and click "Allow" to grant Claude access. 3. **Start using the Sacra connector:** Ask Claude questions about growth & pre-IPO companies, and instruct Claude with "Use the Sacra MCP". Once the connector is active, Claude will have access to the full set of Sacra MCP tools in every conversation. Try prompts like "Use the Sacra MCP to write an investment memo on Figma" or "Use Sacra to pull the latest revenue signals for Canva and summarize the key trends." Claude will call the appropriate tools and ground its response in Sacra's data. # Overview - MCP Source: https://docs.sacra.com/mcp-overview Connect AI agents to Sacra's private company data using the Model Context Protocol Sacra exposes its company data API as an MCP server, letting AI agents call Sacra tools — company profiles, funding rounds, revenue signals, recent news, and in-depth research reports — directly inside a conversation. There are three ways to connect depending on whether you want a no-code integration with an existing AI app, a backend integration you control, or a third-party platform that supports custom MCP servers. For a product overview, see [Sacra MCP](https://sacra.com/features/mcp). Connect Sacra to ChatGPT or Claude via OAuth — no API key or code required. Call Sacra MCP from your own backend using a Sacra API key and any agent SDK. Connect Sacra to Intercom Fin, Cursor, Windsurf, and any other MCP-compatible platform. ## ChatGPT & Claude clients The fastest way to get started. Sacra is available as an [official app in ChatGPT](https://chatgpt.com/plugins/plugin_asdk_app_6994e1a4aa408191846109195ecfa307) and an [official connector in the Claude directory](https://claude.ai/directory/connectors/sacra) — install with one click and sign in via OAuth, no API key or code required. Once connected, you can ask either app to look up companies, pull funding history, or generate investment memos grounded in Sacra data just by telling it to use Sacra. Install the official Sacra app from ChatGPT's app directory and authenticate via OAuth. Connect the official Sacra connector from the Claude directory and authenticate via OAuth. ## Server-side agents / SDKs For building your own backend features — a company brief generator, a research copilot, or a chat experience — Sacra MCP can be called directly from your server using a Sacra API key. You connect to `https://mcp.sacra.com/mcp` over Streamable HTTP, pass the key in the `Authorization` header, and use any agent SDK to orchestrate calls to Sacra tools. The server-side article includes a full TypeScript example using the OpenAI Agents SDK that generates an investor-style company brief. Full walkthrough with prerequisites, environment setup, and a working TypeScript example. ## Integrations via MCP Sacra MCP works in any platform that accepts a custom MCP server URL — Intercom Fin, Cursor, Windsurf, Zed, and more. Point the platform at `https://mcp.sacra.com/mcp` and authenticate with OAuth or a Sacra API key. How-to guides for Intercom Fin, Cursor, and a platform reference table. A deep dive into the available MCP tools and how agents chain them together to answer real questions. # Server-side agents / SDKs - MCP Source: https://docs.sacra.com/mcp-server-side Connect to Sacra's MCP server from your own backend using a Sacra API key Sacra MCP can be used server-side with a normal Sacra API key. This is the recommended setup if you want to build a user-facing feature like a company brief generator, research copilot, or chat experience powered by Sacra tools. This example uses the OpenAI Agents SDK with Sacra's MCP server over Streamable HTTP. ## High-level flow 1. Create a Sacra API key in your [Organization Settings](https://sacra.com/orgs/settings/general/). 2. Store it as `SACRA_API_TOKEN` in your server environment. 3. Connect to `https://mcp.sacra.com/mcp`. 4. Pass the API key in the `Authorization` header as `Token YOUR_API_KEY`. 5. Run an agent that uses Sacra MCP tools to generate a company brief. ## Prerequisites * [Sacra account with API access](https://sacra.com/signup/) * Sacra API key * OpenAI API key * TypeScript / Node environment Install dependencies: ```bash theme={null} npm install @openai/agents ``` ## Environment variables Configure the following: ```bash theme={null} SACRA_API_TOKEN=... OPENAI_API_KEY=... ``` Do not commit API keys to source control. ## Migration note for existing M2M users If you previously used the legacy M2M flow, migrate to API key auth: * Remove the Stytch token exchange step. * Stop sending `Authorization: Bearer ...`. * Use a Sacra API key from your [Organization Settings](https://sacra.com/orgs/settings/general/). * Send it as `Authorization: Token YOUR_API_KEY`. ## Example: Build a company brief generator This example asks an agent to generate a concise investor-style company brief for `openai.com` using Sacra MCP tools. ```ts theme={null} import { Agent, MCPServerStreamableHttp, run } from "@openai/agents"; export async function generateCompanyBrief(domain: string = "openai.com") { const { OPENAI_API_KEY, SACRA_API_TOKEN } = process.env; if (!OPENAI_API_KEY) { throw new Error("Missing OPENAI_API_KEY"); } if (!SACRA_API_TOKEN) { throw new Error("Missing SACRA_API_TOKEN"); } const mcpServer = new MCPServerStreamableHttp({ name: "sacra_research_tools", url: "https://mcp.sacra.com/mcp", requestInit: { headers: { Authorization: `Token ${SACRA_API_TOKEN}`, }, }, }); const agent = new Agent({ name: "CompanyBriefAgent", model: "gpt-5-mini", instructions: ` You are a Company Brief Agent. Your goal is to create a concise investor-style company brief using Sacra MCP tools. First, use get_company_profile with the provided company_domain. Then use get_funding_rounds_for_company. Then use get_news_for_company for recent developments. If the company profile includes documents and one looks useful, you may use get_document_content to pull extra context from one relevant Sacra document. Format your response as follows: # [Company Name] **Overview:** [2-4 sentences on what the company does and why it matters] **Founding and key people:** - [founding year and key people] **Funding history:** - [important funding rounds, investors, valuations if available] **Recent developments:** - [important recent news items from Sacra] **Why it matters:** - [short investor-style takeaway] Keep the output concise, factual, and grounded in the Sacra tool results. `, mcpServers: [mcpServer], }); try { await mcpServer.connect(); const result = await run( agent, `Create a concise investor-style company brief for ${domain}. Include the business overview, founding and key people, funding history, recent developments, and why the company matters.`, ); return result.finalOutput; } finally { await mcpServer.close().catch(() => {}); } } ``` ## What this example does * Connects directly to Sacra MCP at `https://mcp.sacra.com/mcp` * Authenticates with `Authorization: Token YOUR_API_KEY` * Uses Sacra MCP tools to gather company profile, funding, and recent news * Returns a concise company brief that can power a user-facing feature ## Security notes * Store `SACRA_API_TOKEN` in a secure secret manager or server environment. * Never expose your API key in client-side code. * Rotate API keys from your Sacra organization settings if needed. # Quickstart - Getting started Source: https://docs.sacra.com/quickstart Get started with the Sacra API in minutes ## Get your API key Before making requests you need an organization API token. If you don't have a Sacra account yet, [sign up](https://sacra.com/signup/) to get started. 1. Sign in to [Sacra](https://sacra.com/login) and navigate to your organization settings. 2. Go to **API Keys** and click **Create API Key**. 3. Give the key a name (e.g. `my-app`) and copy the token — you won't be able to see it again. Pass the token in the `Authorization` header on every request: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/?company_domain=stripe.com" ``` A successful response confirms your token is valid: ```json theme={null} { "company": { "domain": "stripe.com", "name": "Stripe", "slug": "stripe" } } ``` ## Make your first request Fetch company data by domain: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/companies/?company_domain=stripe.com" ``` Get the latest research documents for a company: ```bash theme={null} curl -H "Authorization: Token YOUR_API_KEY" \ "https://sacra.com/api/v1/documents/?company_domain=stripe.com" ``` Use `page_after` and `page_before` cursors from the `pagination` object to page through results. Search documents and companies by keyword: ```bash theme={null} curl -X POST \ -H "Authorization: Token YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query": "fintech revenue"}' \ https://sacra.com/api/v1/search/ ``` ## Core concepts Look up companies by domain, slug, or ID. Returns financials, milestones, and metadata. Browse market research, company one-pagers, and interview transcripts. Full-text search across all documents and companies. Access company events and financial metrics. ## Pagination Most list endpoints return paginated results. The `pagination` object in each response tells you how to fetch the next page. **Cursor-based** (documents, events, metrics, news): ```json theme={null} { "pagination": { "page_size": 30, "total_items": 142, "next_link": "https://sacra.com/api/v1/documents/?page_after=abc123" } } ``` **Offset-based** (search, category items): ```json theme={null} { "pagination": { "limit": 20, "offset": 0, "total": 85, "next_offset": 20 } } ``` Follow the `next_link` URL directly — it includes all the query parameters you need. ## Next steps Explore the full API reference with request and response schemas. Embed company data, charts, and research documents into your site. Understand revenue data types, datapoint periods, and how to interpret financial data. Connect to the Sacra MCP server for AI agent integration.