dealroom-early-access-api

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Dealroom API consumer guide

Dealroom API 使用指南

How to build against the Dealroom next-gen REST API: authenticate, pick the right endpoint, and discover filters from the live API instead of guessing.
This skill covers Programmatic (M2M) API usage. Application (PKCE) keys for browser SPAs also exist (read-only, created from the same settings page), but this skill does not cover that flow.
This skill holds only the durable parts (auth, endpoint judgment, discovery mechanism, pointers). Endpoint shapes, the full filter catalog, and field lists live in the API itself and the docs, which are the single source of truth. Always read those for specifics rather than relying on memory.
如何基于Dealroom下一代REST API进行开发:认证、选择合适的端点,并从实时API中发现过滤器,而非猜测。
本技能涵盖程序化(M2M)API使用。适用于浏览器SPA的应用(PKCE)密钥也存在(只读,从同一设置页面创建),但本技能不涵盖该流程。
本技能仅保留持久化内容(认证、端点判断、发现机制、指引)。端点结构、完整过滤器目录和字段列表存储在API本身及文档中,它们是唯一的事实来源。如需具体细节,请始终查阅这些内容,而非依赖记忆。

Read this before building anything

开始构建前必读

Two failure modes cause almost every stuck integration. Avoid both:
  1. Don't guess endpoint paths, filter keys, or operator syntax. Hallucinated names that "look right" return empty results or
    400
    s. Discover filters at runtime with
    GET /reference/filters?scope=<scope>
    and confirm shapes against the OpenAPI spec.
  2. Don't default to aggregate endpoints. This is the most common mistake. Most questions want records, not a computed statistic. See below.
This is an early-access API and can change without notice. If the live behavior conflicts with this skill, trust the API and flag it: see When the API disagrees with this skill.
两种失败模式几乎导致了所有集成受阻。请避免这两种情况:
  1. 不要猜测端点路径、过滤器键或运算符语法。 那些“看起来正确”的虚构名称会返回空结果或
    400
    错误。通过
    GET /reference/filters?scope=<scope>
    在运行时发现过滤器,并根据OpenAPI规范确认结构。
  2. 不要默认使用聚合端点。 这是最常见的错误。大多数问题需要的是记录,而非计算得出的统计数据。请见下文。
这是一个早期访问API,可能会随时更改,恕不另行通知。如果实时行为与本技能描述冲突,请以API为准并标记问题:请查看当API与本技能描述不符时

Choosing the right endpoint

选择合适的端点

The most important decision. Pick by what the answer is, not by how analytical the question sounds.
Rule of thumb: If the user wants to see things (a list of companies, the rounds of one startup, who invested in X), use a transactional / list endpoint. If they want a number or a chart of numbers computed across many rows (count, sum, average, median, distribution, trend, cross-tab), use an aggregate endpoint. When in doubt, start transactional.
List endpoints already return rich nested objects (funding summary, latest valuation, tags, founders) and a
page.total
count, so you rarely need a separate aggregate just to enrich or count a result set.
The user wantsUseNot
A list of companies / investors / people matching criteria
GET /data/entities
(or
/data/investors
,
/data/founders
,
/data/people
)
aggregate
The "top N by funding / valuation / signal"list +
sort=-<field>
+
limit=N
aggregate group_by
Everything about one entity
GET /data/entities/{id}
aggregate
One entity's rounds / valuations / investors / portfolio / teamtyped collections (see below):
GET /data/companies/{id}/{funding-rounds,valuations,investors,team}
,
/data/investors/{id}/{portfolio,funds}
aggregate
All funding rounds matching criteria
GET /data/transactions
aggregate
All valuations matching criteria (cross-entity)
GET /data/valuations
aggregate
Fund vehicles investor firms have raised (cross-manager)
GET /data/funds
/data/investors
Points to plot on a map
GET /data/{companies,investors,universities}/geo
(slim dots; see below)
a full list call you then thin client-side
How many entities match (just the count)the list call's
page.total
(
include_total=true
)
an aggregate for a bare count
A count / sum / avg / median grouped by a dimension
GET /analytics/aggregate/{source}
paging the list and reducing client-side
Several metrics at once (KPIs, leaderboards)
GET /analytics/aggregate/{source}/multi-metric
many separate calls
A 2D matrix, stage transitions, or a per-year trend
GET /analytics/funding-analytics/{heatmap,round-transitions,funnel}
,
/analytics/timeseries
Fuzzy name lookup ("find Stripe")
GET /data/search
(all five collections; narrow with
types=
; returns a flat
data
array, each row carries its
type
)
a
/data/entities
name filter
Ranked investor recommendations for a target company
GET /analytics/matching/investors
hand-rolled portfolio-overlap queries
Companies / investors similar to a given one
GET /data/companies/{id}/similar
,
/data/investors/{id}/similar
building your own tag-overlap ranking
Anti-patterns:
  • Ranking entities via aggregate.
    group_by
    groups by a dimension (country, year, sector), not by entity. To rank companies, use the list endpoint with
    sort
    .
  • Aggregating to count. A list response already returns
    page.total
    .
  • Aggregating one entity. Profile data lives on the typed-collection sub-resources (see below).
  • The reverse mistake: paging thousands of list rows to sum/average client-side. That is exactly what
    GET /analytics/aggregate/{source}
    is for.
Relationship sub-resources are facet-scoped by entity type. They are not on
/data/entities/{id}
(that path carries only the detail record plus
lp-funds
). Read the entity's
type
/
organization_subtype
/
is_investor
/
is_founder
flags from the detail payload, then call the matching typed collection. The paths are static and knowable:
  • Companies (
    /data/companies/{id}/
    ):
    funding-rounds
    ,
    valuations
    ,
    financials
    ,
    investors
    ,
    team
    ,
    headcount-breakdown
    ,
    web-traffic
    ,
    similar
  • Investors (
    /data/investors/{id}/
    ):
    portfolio
    ,
    funds
    ,
    lp-funds
    ,
    team
    ,
    similar
  • People / founders / universities:
    /data/people/{id}/career
    ,
    /data/founders/{id}/founded-companies
    ,
    /data/universities/{id}/alumni
    , and
    team
    on universities / gov-ngo
The
similar
collections rank by weighted tag overlap (force-sorted by score), accept the full company/investor filter DSL to narrow the pool, and use offset pagination capped at
offset + limit <= 1000
.
Map points have their own slim lens.
GET /data/{companies,investors,universities}/geo
returns one point per entity (id, name, coordinates) instead of the full list payload, takes the same
filter
as its list endpoint, and accepts
size_by=<numeric dimension>
(e.g.
total_funding
,
employee_count
,
latest_valuation
,
total_invested
,
total_investments_count
,
alumni_count
,
alumni_founder_count
) to return each point's
value
for proportional sizing.
size_by
also sorts descending, so a capped response keeps the highest-value points; entities without usable coordinates are omitted. For per-area counts (a choropleth rather than dots) use
GET /analytics/aggregate/companies?metric=count&group_by=map_area
instead. The older generic
GET /data/entities/geo
still exists (no
size_by
, higher limits) but prefer the per-collection endpoints.
这是最重要的决策。应根据答案是什么来选择,而非问题听起来有多具分析性。
经验法则: 如果用户想要查看内容(公司列表、某初创企业的融资轮次、谁投资了X),请使用事务型/列表端点。如果他们想要基于多行数据计算得出的数字或数字图表(计数、求和、平均值、中位数、分布、趋势、交叉表),请使用聚合端点。如有疑问,从事务型端点开始。
列表端点已返回丰富的嵌套对象(融资摘要、最新估值、标签、创始人)和
page.total
计数,因此你很少需要单独使用聚合端点来丰富或计数结果集。
用户需求使用端点不使用
符合条件的公司/投资者/人物列表
GET /data/entities
(或
/data/investors
/data/founders
/data/people
聚合端点
“按融资/估值/信号排名前N的实体”列表端点 +
sort=-<field>
+
limit=N
聚合端点的group_by功能
某实体的所有信息
GET /data/entities/{id}
聚合端点
某实体的融资轮次/估值/投资者/投资组合/团队类型化集合(见下文):
GET /data/companies/{id}/{funding-rounds,valuations,investors,team}
/data/investors/{id}/{portfolio,funds}
聚合端点
符合条件的所有融资轮次
GET /data/transactions
聚合端点
符合条件的所有估值(跨实体)
GET /data/valuations
聚合端点
投资公司筹集的基金载体(跨管理人)
GET /data/funds
/data/investors
要在地图上绘制的点
GET /data/{companies,investors,universities}/geo
(精简点数据;见下文)
获取完整列表后在客户端精简数据的调用
符合条件的实体数量(仅计数)列表调用的
page.total
(需设置
include_total=true
用于单纯计数的聚合端点
按维度分组的计数/求和/平均值/中位数
GET /analytics/aggregate/{source}
分页获取列表后在客户端计算
多个指标(KPI、排行榜)
GET /analytics/aggregate/{source}/multi-metric
多次单独调用
二维矩阵、阶段转换或年度趋势
GET /analytics/funding-analytics/{heatmap,round-transitions,funnel}
/analytics/timeseries
模糊名称查找(“查找Stripe”)
GET /data/search
(涵盖五个集合;可通过
types=
缩小范围;返回扁平化的
data
数组,每行包含其
type
/data/entities
的名称过滤器
针对目标公司的投资者推荐排名
GET /analytics/matching/investors
手动编写的投资组合重叠查询
与给定实体相似的公司/投资者
GET /data/companies/{id}/similar
/data/investors/{id}/similar
自行构建标签重叠排名
反模式:
  • 通过聚合端点对实体排名。
    group_by
    是按维度(国家、年份、行业)分组,而非按实体。要对公司排名,请使用带
    sort
    参数的列表端点。
  • 使用聚合端点进行计数。 列表响应已返回
    page.total
  • 对单个实体使用聚合端点。 实体详情数据存储在类型化集合的子资源中(见下文)。
  • 反向错误: 分页获取数千条列表数据后在客户端求和/平均。这正是
    GET /analytics/aggregate/{source}
    的用途。
关系子资源按实体类型的维度划分范围。 它们不在
/data/entities/{id}
路径下(该路径仅携带详情记录及
lp-funds
)。从详情负载中读取实体的
type
/
organization_subtype
/
is_investor
/
is_founder
标志,然后调用匹配的类型化集合。路径是固定且可知的:
  • 公司
    /data/companies/{id}/
    ):
    funding-rounds
    valuations
    financials
    investors
    team
    headcount-breakdown
    web-traffic
    similar
  • 投资者
    /data/investors/{id}/
    ):
    portfolio
    funds
    lp-funds
    team
    similar
  • 人物/创始人/大学
    /data/people/{id}/career
    /data/founders/{id}/founded-companies
    /data/universities/{id}/alumni
    ,以及大学/政府非盈利组织的
    team
similar
集合通过加权标签重叠进行排名(按分数强制排序),接受完整的公司/投资者过滤器DSL来缩小范围,并使用偏移分页,上限为
offset + limit <= 1000
地图点有专门的精简视图。
GET /data/{companies,investors,universities}/geo
返回每个实体的一个点(ID、名称、坐标),而非完整的列表负载,接受与其列表端点相同的
filter
参数,并支持
size_by=<numeric dimension>
(例如
total_funding
employee_count
latest_valuation
total_invested
total_investments_count
alumni_count
alumni_founder_count
)来返回每个点的
value
以进行比例缩放。
size_by
还会按降序排序,因此限制数量的响应会保留最高值的点;没有可用坐标的实体将被省略。如需按区域计数( choropleth地图而非点),请改用
GET /analytics/aggregate/companies?metric=count&group_by=map_area
。旧的通用
GET /data/entities/geo
仍存在(无
size_by
,更高限制),但优先使用按集合划分的端点。

Setup

设置步骤

Steps 1-2 apply to both modes; run them on the first turn and skip what is already done. Step 3 is only for app builds (see Two ways to call the API).
  1. Generate an API key (the user must do this). Auth0 needs a logged-in browser, so you cannot do it for them. Tell them: open https://beta.dealroom.app/settings/api, click + Create key, choose Programmatic (M2M), and copy both
    client_id
    and
    client_secret
    (the secret is shown only once). The API is in closed beta: if that page shows a waitlist sign-up instead of + Create key, the account has no API access yet - the user should join the waitlist and wait for the enablement email; there is no way around this gate.
  2. Store the credentials in
    .env
    .
    Copy
    assets/.env.example
    and fill in
    DEALROOM_CLIENT_ID
    and
    DEALROOM_CLIENT_SECRET
    . Optionally set
    DEALROOM_USER_AGENT
    for server-side observability. Confirm
    .env
    is in
    .gitignore
    .
  3. App builds only - copy a client snippet. Python:
    cp <skill-path>/assets/snippets/dealroom.py ./
    then
    pip install authlib requests python-dotenv
    . Node/TS: copy
    dealroom.ts
    plus
    assets/package.json
    and
    assets/tsconfig.json
    (the ESM config the snippet needs), then
    npm install
    and verify with
    npm run sanity
    . Both read
    .env
    , send the headers, and mint and refresh tokens automatically. For one-off conversational queries, skip this and use curl (next section).
步骤1-2适用于两种模式;在首次使用时执行,跳过已完成的步骤。步骤3仅适用于应用构建(见两种调用API的方式)。
  1. 生成API密钥(必须由用户操作)。 Auth0需要已登录的浏览器,因此你无法代劳。请告知用户:打开https://beta.dealroom.app/settings/api,点击**+ Create key**,选择Programmatic (M2M),并复制
    client_id
    client_secret
    (密钥仅显示一次)。此API处于封闭测试阶段:如果该页面显示等待列表注册而非**+ Create key**,则该账户尚未获得API访问权限——用户应加入等待列表并等待启用邮件;无法绕过此限制。
  2. 将凭据存储在
    .env
    文件中。
    复制
    assets/.env.example
    并填写
    DEALROOM_CLIENT_ID
    DEALROOM_CLIENT_SECRET
    。可选设置
    DEALROOM_USER_AGENT
    以便服务器端可观测性。确认
    .env
    已添加到
    .gitignore
    中。
  3. 仅适用于应用构建 - 复制客户端代码片段。 Python:
    cp <skill-path>/assets/snippets/dealroom.py ./
    ,然后执行
    pip install authlib requests python-dotenv
    。Node/TS:复制
    dealroom.ts
    以及
    assets/package.json
    assets/tsconfig.json
    (代码片段所需的ESM配置),然后执行
    npm install
    并通过
    npm run sanity
    验证。两者均读取
    .env
    文件、发送请求头,并自动生成和刷新令牌。对于一次性对话式查询,请跳过此步骤并使用curl(下一节)。

Two ways to call the API

两种调用API的方式

Match the tool to the job. Do not scaffold a project or write a script just to answer a question; do not hand-mint tokens in a loop inside a real program.
Conversational / ad-hoc - you answering a question now: run curl directly. This is the default when the user asks you to look something up, explore, or sanity-check data. Mint one token per session, reuse it across calls, and pass each filter with
curl -G --data-urlencode
so the
[
,
]
, and
|
metacharacters survive the shell. No files, no project, no snippet.
bash
undefined
根据任务选择合适的工具。不要仅为回答问题而搭建项目或编写脚本;不要在实际程序中循环手动生成令牌。
对话式/临时查询 - 你现在需要回答问题:直接运行curl。 当用户要求你查询、探索或验证数据时,默认使用此方式。每个会话生成一次令牌,在多次调用中复用,并通过
curl -G --data-urlencode
传递每个过滤器,以便
[
]
|
元字符在shell中保留。无需文件、项目或代码片段。
bash
undefined

Load credentials and mint a token ONCE per session (24h lifetime); reuse $TOKEN after.

加载凭据并生成令牌(每个会话仅执行一次,令牌有效期24小时);之后复用$TOKEN。

NOTE: the audience is NOT the API base URL - it stays the legacy Auth0 API

注意:audience不是API基础URL - 即使请求发送到api.beta.dealroom.app,它仍保留旧版Auth0 API标识符(https://api-next.beta.dealroom.co)。请见下方环境表。

identifier (https://api-next.beta.dealroom.co) even though requests go to

api.beta.dealroom.app. See the environment table below.

set -a && . ./.env && set +a TOKEN=$(curl -s https://accounts.beta.dealroom.co/oauth/token
-H 'Content-Type: application/json'
-d "{"grant_type":"client_credentials","client_id":"$DEALROOM_CLIENT_ID","client_secret":"$DEALROOM_CLIENT_SECRET","audience":"https://api-next.beta.dealroom.co\"}"
| jq -r .access_token)
curl -s -G 'https://api.beta.dealroom.app/data/entities'
--data-urlencode 'filter=and(organization_subtype[eq]:company,tag_id[in_any]:42|99)'
--data-urlencode 'sort=-total_funding' --data-urlencode 'limit=5'
-H "Authorization: Bearer $TOKEN" -H "X-Client-Id: $DEALROOM_CLIENT_ID" | jq

**Building an app or anything repeated - code that outlives the session: use the snippet.**
Copy `dealroom.py` / `dealroom.ts` into the project. It reads `.env`, sends the headers, and
re-mints the token on a `401` automatically - which raw curl will not do when the 24h token
expires mid-run. This is the right path inside any program, loop, or multi-query tool.

**Pitfall either way: never put raw `[ ] |` in a curl URL string.** Use `-G
--data-urlencode` per parameter (or the snippet's structured params). Bare brackets in the
URL are the single biggest cause of agents writing throwaway escape scripts.
set -a && . ./.env && set +a TOKEN=$(curl -s https://accounts.beta.dealroom.co/oauth/token
-H 'Content-Type: application/json'
-d "{"grant_type":"client_credentials","client_id":"$DEALROOM_CLIENT_ID","client_secret":"$DEALROOM_CLIENT_SECRET","audience":"https://api-next.beta.dealroom.co\"}"
| jq -r .access_token)
curl -s -G 'https://api.beta.dealroom.app/data/entities'
--data-urlencode 'filter=and(organization_subtype[eq]:company,tag_id[in_any]:42|99)'
--data-urlencode 'sort=-total_funding' --data-urlencode 'limit=5'
-H "Authorization: Bearer $TOKEN" -H "X-Client-Id: $DEALROOM_CLIENT_ID" | jq

**构建应用或重复执行的任务 - 代码需长期存在:使用代码片段。** 将`dealroom.py`/`dealroom.ts`复制到项目中。它会读取`.env`文件、发送请求头,并在收到`401`错误时自动刷新令牌——而原始curl在24小时令牌过期时不会执行此操作。这是任何程序、循环或多查询工具中的正确选择。

**两种方式的陷阱:永远不要在curl URL字符串中直接使用原始的`[ ] |`。** 对每个参数使用`-G --data-urlencode`(或代码片段的结构化参数)。URL中的裸括号是导致代理编写一次性转义脚本的最常见原因。

Authentication

认证

  • Flow: OAuth2 client-credentials (machine-to-machine). Exchange
    client_id
    /
    client_secret
    for a Bearer token, then send it on every call. The snippets do this for you.
  • Two mandatory headers on every request:
    Authorization: Bearer <token>
    and
    X-Client-Id: <client_id>
    (missing it is a
    400
    ). A custom
    User-Agent
    is optional and useful for server-side observability, but it is not part of authentication.
  • Token lifetime: 24h. Cache and reuse; do not mint per call. Snippets refresh on
    401
    . A key deactivated in the UI is rejected on its next request even while its token is still inside that 24h window, so a
    401
    that survives one refresh means the key is dead, not expired: stop and tell the user rather than re-minting in a loop.
  • Mutations (POST / PATCH / PUT / DELETE) additionally need the relevant write/delete permission on the key.
  • 流程: OAuth2客户端凭证(机器到机器)。将
    client_id
    /
    client_secret
    兑换为Bearer令牌,然后在每次调用时发送。代码片段会自动完成此操作。
  • 每次请求必须包含两个请求头:
    Authorization: Bearer <token>
    X-Client-Id: <client_id>
    (缺少会返回
    400
    错误)。自定义
    User-Agent
    是可选的,有助于服务器端可观测性,但不属于认证的一部分。
  • 令牌有效期: 24小时。缓存并复用;不要每次调用都生成。代码片段会在收到
    401
    时刷新。即使令牌仍在24小时有效期内,在UI中已停用的密钥也会在下次请求时被拒绝,因此如果刷新一次后仍收到
    401
    ,则表示密钥已失效,而非过期:请停止操作并告知用户,而非循环生成令牌。
  • 修改操作(POST/PATCH/PUT/DELETE)还需要密钥具备相应的写入/删除权限。

A missing token does not fail loudly - check that your auth applied

缺少令牌不会明显报错 - 请检查认证是否生效

Read endpoints also serve anonymous callers (that is how public ecosystem pages work), so a request with no or a dropped
Authorization
header returns
200
with a thinner row rather than
401
. Two markers tell you which principal the API actually saw:
  • page.tier
    -
    anonymous
    /
    free
    /
    premium
    , alongside
    page.capped
    and
    page.ecosystem
    . Present only for non-M2M callers on capped resources.
  • locked[]
    - a top-level array of
    { field, reason, unlock }
    for fields redacted (nulled, not omitted) at that tier, e.g.
    { "field": "website", "reason": "ACCOUNT_REQUIRED", "unlock": "signup" }
    . Added only when something was actually redacted.
A
page.tier
of
anonymous
or a
locked[]
on a call you made with a key means your credentials did not apply.
Fix the headers; do not report the nulls as missing data. M2M callers are exempt from field redaction and from the per-tier page-size and pagination-depth caps below, so a correctly authenticated response has neither marker.
The default environment is beta. For other environments, swap the base URL, Auth0 host, and audience per this table. The OAuth2
audience
is NOT the API base URL
on beta/production: the platform moved to
dealroom.app
but the Auth0 API identifier kept its legacy
api-next.*.dealroom.co
value. Minting a token with the base URL as audience fails.
EnvironmentAPI base URLAuth0 hostOAuth2
audience
Beta
https://api.beta.dealroom.app
accounts.beta.dealroom.co
https://api-next.beta.dealroom.co
Production
https://api.dealroom.app
accounts.dealroom.co
https://api-next.dealroom.co
Staging
https://api-next.staging.dealroom.dev
accounts.staging.dealroom.dev
https://api-next.staging.dealroom.dev
The former
api-next.beta.dealroom.co
/
api-next.dealroom.co
hosts are retired and no longer serve traffic - update any old base URLs to the
dealroom.app
hosts. The strings live on only as Auth0 audience identifiers.
读取端点也为匿名调用者提供服务(这是公共生态系统页面的工作方式),因此没有或丢失
Authorization
头的请求会返回
200
,但返回的数据行更精简,而非
401
错误。有两个标记可告诉你API实际识别的身份:
  • page.tier
    -
    anonymous
    /
    free
    /
    premium
    ,与
    page.capped
    page.ecosystem
    一起返回。仅在非M2M调用者访问受限资源时出现。
  • locked[]
    - 顶层数组,包含因当前层级而被编辑(设为null,而非省略)的字段,例如
    { "field": "website", "reason": "ACCOUNT_REQUIRED", "unlock": "signup" }
    。仅当实际有字段被编辑时才会添加。
如果使用密钥调用时返回
page.tier
anonymous
或出现
locked[]
,则表示你的凭据未生效。
请修复请求头;不要将null值报告为缺失数据。M2M调用者不受字段编辑限制,也不受下文所述的每层页面大小和分页深度限制,因此正确认证的响应不会包含这两个标记。
默认环境为beta。对于其他环境,请根据下表替换基础URL、Auth0主机和audience。在beta/生产环境中,OAuth2的
audience
不是API基础URL
:平台已迁移到
dealroom.app
,但Auth0 API标识符仍保留旧版
api-next.*.dealroom.co
的值。使用基础URL作为audience生成令牌会失败。
环境API基础URLAuth0主机OAuth2
audience
Beta
https://api.beta.dealroom.app
accounts.beta.dealroom.co
https://api-next.beta.dealroom.co
生产环境
https://api.dealroom.app
accounts.dealroom.co
https://api-next.dealroom.co
Staging
https://api-next.staging.dealroom.dev
accounts.staging.dealroom.dev
https://api-next.staging.dealroom.dev
旧版
api-next.beta.dealroom.co
/
api-next.dealroom.co
主机已停用,不再提供服务——请将任何旧的基础URL更新为
dealroom.app
主机。这些字符串仅作为Auth0 audience标识符保留。

API versioning

API版本控制

The API is date-versioned (Stripe-style). Send an optional
API-Version: YYYY-MM-DD
header to pin behavior; omit it to get the latest version (what new integrations should do). Clients pinned to an older date keep their old request/response shapes via server-side transforms until that version's sunset date, so existing code does not break when the API moves.
There is no
/api
path prefix.
Every namespace is served at the root of the API host:
/data/*
,
/analytics/*
,
/reference/*
,
/platform/*
,
/system/*
. Old
/api/*
URLs from earlier integrations are permanently redirected (
308
, all versions, no sunset), so they still work - but write new code against the root paths and drop
/api
from any base URL you find in existing code.
Every breaking change, deprecation, and addition is listed in the changelog with the version date and affected endpoints. If you are returning to a project built against an earlier version of this skill, or anything here looks stale, read the changelog first - it is the fastest way to see what moved. This skill deliberately keeps no per-version change list: the live changelog is the single source of truth for what changed when.
API采用日期版本控制(Stripe风格)。发送可选的
API-Version: YYYY-MM-DD
头以固定行为;省略该头将获取最新版本(新集成应采用此方式)。固定到旧版本的客户端将通过服务器端转换保留其旧的请求/响应结构,直到该版本的终止日期,因此现有代码不会因API更新而中断。
没有
/api
路径前缀。
所有命名空间都在API主机的根目录下提供:
/data/*
/analytics/*
/reference/*
/platform/*
/system/*
。早期集成中的旧版
/api/*
URL会被永久重定向(
308
,所有版本,无终止日期),因此它们仍然有效——但请针对根路径编写新代码,并从现有代码中删除
/api
前缀。
所有重大变更、弃用和新增功能都列在**变更日志**中,包含版本日期和受影响的端点。如果你回到基于本技能早期版本构建的项目,或者此处内容看起来过时,请首先阅读变更日志——这是查看变更内容的最快方式。本技能刻意不保留每个版本的变更列表:实时变更日志是变更内容的唯一事实来源。

Constructing queries

构建查询

Filter grammar

过滤器语法

All list and aggregate endpoints take a
filter
query parameter:
text
filter=key[op]:value                                          # single
filter=and(key1[op]:val1,key2[op]:val2)                       # AND (comma-separated args)
filter=or(key1[op]:val1,key2[op]:val2)                        # OR
filter=and(tag_id[eq]:42,or(location[eq]:1234,location[eq]:5678))   # nested
Operators:
eq
,
neq
,
gt
,
gte
,
lt
,
lte
, and the multi-value
in_any
/
in_all
/
nin_any
/
nin_all
(pipe-separated, e.g.
tag_id[in_any]:1|2|3
).
in_all
/
nin_all
apply only to junction filters (tags, growth stages). Booleans are strings (
true
/
false
). Relationship-path filters reach related entities with
.
(one hop) and
__
(two hops), e.g.
founder.gender[eq]:female
,
funding_round__investor.total_invested[gt]:1000000
.
Entity classification (the legacy
is_company
flags were removed):
type
is
organization
or
person
;
organization_subtype
is
company
,
investor
,
university
, or
gov_ngo
; role flags
is_investor
/
is_founder
/
is_executive
/
is_partner
stack on top. So "companies" is
organization_subtype[eq]:company
, "investment firms" is
organization_subtype[eq]:investor
, "people" is
type[eq]:person
. (The investor-firm subtype was renamed from
fund
to
investor
;
fund
now refers only to the investment vehicle and is no longer a valid
organization_subtype
value.)
The exact key list, operators, and value types per scope are not memorized here. Discover them live (next section) or read the Filters & Sorting reference.
所有列表和聚合端点都接受
filter
查询参数:
text
filter=key[op]:value                                          # 单个条件
filter=and(key1[op]:val1,key2[op]:val2)                       # AND(逗号分隔参数)
filter=or(key1[op]:val1,key2[op]:val2)                        # OR
filter=and(tag_id[eq]:42,or(location[eq]:1234,location[eq]:5678))   # 嵌套条件
运算符:
eq
neq
gt
gte
lt
lte
,以及多值运算符
in_any
/
in_all
/
nin_any
/
nin_all
(竖线分隔,例如
tag_id[in_any]:1|2|3
)。
in_all
/
nin_all
仅适用于关联过滤器(标签、成长阶段)。布尔值为字符串(
true
/
false
)。关系路径过滤器使用
.
(单跳)和
__
(双跳)访问关联实体,例如
founder.gender[eq]:female
funding_round__investor.total_invested[gt]:1000000
实体分类(旧版
is_company
标志已移除):
type
organization
person
organization_subtype
company
investor
university
gov_ngo
;角色标志
is_investor
/
is_founder
/
is_executive
/
is_partner
可叠加。因此“公司”对应
organization_subtype[eq]:company
,“投资公司”对应
organization_subtype[eq]:investor
,“人物”对应
type[eq]:person
。(投资公司子类型已从
fund
重命名为
investor
fund
现在仅指投资载体,不再是有效的
organization_subtype
值。)
每个范围的准确键列表、运算符和值类型未在此处记忆。请在运行时发现(下一节)或阅读过滤器与排序参考

Discover filters and resolve IDs (do not guess)

发现过滤器并解析ID(不要猜测)

There are two ID families - never mix them up:
  • Taxonomy IDs are numeric (locations, industries, tags, degrees, backgrounds), not strings:
    location[eq]:United+States
    returns nothing;
    location[eq]:233
    works.
  • Entity IDs are UUIDs - every path
    {id}
    param and every entity-reference filter (
    entity_id
    ,
    investor_id
    ,
    company_investor_id
    ,
    portfolio_company_id
    , and relationship
    .id
    paths like
    founder__university.id
    ). An integer where a UUID is expected fails validation or matches nothing.
Discover and resolve at runtime:
bash
GET /reference/filters?scope=companies              # valid filter keys, operators, types, data status
GET /reference/filters/location/values?q=netherlands   # resolve a location to its ID
GET /reference/filters/tag_id/values?q=climate         # resolve a tag across ALL taxonomy types
GET /reference/filters/search?q=climate&scope=companies  # one-shot value search across every filter key
Valid scopes:
companies
,
investors
,
transactions
,
people
,
universities
,
news
,
jobs
. Cache resolved IDs in your app; taxonomy changes rarely.
Build filters from
filter_key
, not the displayed
key
.
/reference/filters
returns tag entries whose
key
is category-qualified (
tag_id:sector
,
tag_id:industry
,
tag_id:technology
, ...) but whose
filter_key
is the bare
tag_id
. The filter grammar only accepts the bare form:
tag_id[eq]:2181301
works;
tag_id:sector[eq]:2181301
throws
FILTER_PARSE_ERROR
("Expected LBRACKET but got COLON"). Always construct filter expressions from each entry's
filter_key
.
Resolve tags without forcing a
type
.
A tag's category is not always what you expect - "Climate Tech" is a
sector
, not an
industry
, so
…/values?q=climate&type=industry
returns
[]
. Omit
type
to search every taxonomy at once; each result is labelled with its own
type
. Only pass
type
to disambiguate. Note: do not trust
entity_count
from these value lookups (it can read
0
even for tags that match hundreds of entities on beta) - confirm real counts with the list call's
page.total
.
有两类ID——切勿混淆:
  • 分类ID为数字(地点、行业、标签、学位、背景),而非字符串:
    location[eq]:United+States
    返回空结果;
    location[eq]:233
    有效。
  • 实体ID为UUID——每个路径
    {id}
    参数和每个实体引用过滤器(
    entity_id
    investor_id
    company_investor_id
    portfolio_company_id
    ,以及关系路径如
    founder__university.id
    )。在需要UUID的位置使用整数会导致验证失败或无匹配结果。
在运行时发现并解析:
bash
GET /reference/filters?scope=companies              # 有效的过滤器键、运算符、类型、数据状态
GET /reference/filters/location/values?q=netherlands   # 将地点解析为ID
GET /reference/filters/tag_id/values?q=climate         # 跨所有分类类型解析标签
GET /reference/filters/search?q=climate&scope=companies  # 一次性搜索所有过滤器键的值
有效范围:
companies
investors
transactions
people
universities
news
jobs
。在应用中缓存解析后的ID;分类变更很少见。
filter_key
构建过滤器,而非显示的
key
/reference/filters
返回的标签条目其
key
带有类别限定(
tag_id:sector
tag_id:industry
tag_id:technology
等),但
filter_key
为裸
tag_id
。过滤器语法仅接受裸形式:
tag_id[eq]:2181301
有效;
tag_id:sector[eq]:2181301
会抛出
FILTER_PARSE_ERROR
(“Expected LBRACKET but got COLON”)。始终从每个条目的
filter_key
构建过滤器表达式。
无需指定
type
即可解析标签。
标签的类别并非总是如你预期——“Climate Tech”是
sector
,而非
industry
,因此
…/values?q=climate&type=industry
返回
[]
。省略
type
以搜索所有分类;每个结果都会标记其自身的
type
。仅在需要消除歧义时传递
type
。注意:不要信任这些值查找中的
entity_count
(在beta环境中,即使标签匹配数百个实体,它也可能显示为
0
)——请通过列表调用的
page.total
确认真实计数。

Pagination, sorting, currency

分页、排序、货币

  • Pagination: offset-based (
    limit
    /
    offset
    ). Some list responses also return
    page.next_cursor
    for keyset pagination; round-trip it opaquely.
    include_total=false
    skips the count for faster lists.
  • Pagination depth is capped for non-M2M callers.
    offset + limit
    above the caller's tier ceiling (anonymous 750 / free 5,000 / premium 50,000, raisable per ecosystem) is a
    400
    PAGINATION_DEPTH_EXCEEDED
    on both the offset and cursor paths - an error, not a silent clamp. M2M keys are exempt. Page size, by contrast, clamps silently for non-M2M callers and reports it via
    page.capped
    .
  • Sorting:
    sort=-total_funding,name
    (prefix
    -
    for descending, comma-separated).
  • Currency:
    ?currency=<ISO 4217>
    converts thresholds and amounts (default USD). Field names stay base names (no
    _usd
    suffix); every response has a top-level
    currency
    .
Limit maximums, sort columns, and response field lists vary by endpoint and are documented in the OpenAPI spec, not here.
  • 分页: 基于偏移量(
    limit
    /
    offset
    )。某些列表响应还返回
    page.next_cursor
    用于键集分页;请直接往返传递该值。
    include_total=false
    可跳过计数以加快列表加载速度。
  • 非M2M调用者的分页深度受限。
    offset + limit
    超过调用者层级上限(匿名用户750/免费用户5,000/付费用户50,000,可按生态系统提升)会在偏移量和游标路径上返回
    400
    错误
    PAGINATION_DEPTH_EXCEEDED
    ——这是错误,而非静默截断。M2M密钥不受此限制。相比之下,页面大小会对非M2M调用者进行静默截断,并通过
    page.capped
    报告。
  • 排序:
    sort=-total_funding,name
    (前缀
    -
    表示降序,逗号分隔)。
  • 货币:
    ?currency=<ISO 4217>
    转换阈值和金额(默认USD)。字段名称保持基础名称(无
    _usd
    后缀);每个响应都包含顶层
    currency
    字段。
限制最大值、排序列和响应字段列表因端点而异,记录在OpenAPI规范中,而非此处。

Live references

实时参考

These are the single source of truth. Fetch the slice you need (
WebFetch
or
curl
); do not paste whole pages or the full spec into context.
NeedWhere
Enumerate namespaces / resources at runtime
GET /
lists the five namespaces; each namespace index (
GET /data
,
GET /analytics
, ...) lists its resources
Exact request/response shape for any endpoint
https://developers.beta.dealroom.co/openapi.yaml
(raw OpenAPI, YAML - slice with `yq '.paths
Browsable endpoint referencethe API Reference tab on
https://developers.beta.dealroom.co
(the API host's
/docs
redirects there; the old on-host Swagger UI at
/openapi
is no longer public)
Guides + concepts (filtering, aggregates, pagination, rate limits)
https://developers.beta.dealroom.co
Full filter + sorting catalog
https://developers.beta.dealroom.co/references/filters-and-sorting
Known limitations (stub / no-data endpoints + filters)
https://developers.beta.dealroom.co/concepts/known-limitations
Changelog (breaking changes, deprecations, new features per version)
https://developers.beta.dealroom.co/changelog
MCP server (Dealroom data as MCP tools for agent clients)
https://developers.beta.dealroom.co/agent-apis/mcp
Some advertised endpoints and filters are stubbed or not fully data-loaded yet, and the set changes over time. Check the known-limitations page, the
x-data-status
extension in the OpenAPI spec, or the
data_status
field from
GET /reference/filters?scope=<scope>
before relying on a surface in production.
这些是唯一的事实来源。获取你需要的部分(
WebFetch
curl
);不要将整个页面或完整规范粘贴到上下文中。
需求来源
在运行时枚举命名空间/资源
GET /
列出五个命名空间;每个命名空间索引(
GET /data
GET /analytics
等)列出其资源
任何端点的确切请求/响应形状
https://developers.beta.dealroom.co/openapi.yaml
(原始OpenAPI,YAML格式——可使用`yq '.paths
可浏览的端点参考
https://developers.beta.dealroom.co
上的API Reference标签(API主机的
/docs
会重定向到此处;旧的主机上Swagger UI位于
/openapi
,现已公开访问)
指南+概念(过滤、聚合、分页、速率限制)
https://developers.beta.dealroom.co
完整过滤器+排序目录
https://developers.beta.dealroom.co/references/filters-and-sorting
已知限制(存根/无数据端点+过滤器)
https://developers.beta.dealroom.co/concepts/known-limitations
变更日志(重大变更、弃用、每个版本的新功能)
https://developers.beta.dealroom.co/changelog
MCP服务器(作为代理客户端MCP工具的Dealroom数据)
https://developers.beta.dealroom.co/agent-apis/mcp
某些宣传的端点和过滤器是存根或尚未完全加载数据,且集合会随时间变化。在生产环境中依赖某个功能之前,请检查已知限制页面、OpenAPI规范中的
x-data-status
扩展,或
GET /reference/filters?scope=<scope>
返回的
data_status
字段。

Common errors

常见错误

SymptomCause and fix
401 Unauthorized
Token expired (24h). The snippet auto-refreshes.
401
that persists after one refresh
The key was deactivated or deleted. Re-minting will not help; ask the user to check https://beta.dealroom.app/settings/api.
400
mentioning
X-Client-Id
The required client-id header is missing or does not match the token.
400
/
UNKNOWN_FILTER
Filter key wrong for this scope. Call
GET /reference/filters?scope=<scope>
.
400
/
FILTER_VALIDATION_ERROR
Enum filter value outside the known set (
round_type
,
investor_type
,
article_type
, ...). Values match case-insensitively by display name or code; discover them via
GET /reference/filters/{key}/values
.
400
/
PAGINATION_DEPTH_EXCEEDED
offset + limit
past the tier depth cap (non-M2M only). Narrow the filter and partition the query instead of paging deeper.
200
with nulled fields and a
locked[]
The call was treated as anonymous or free. Your credentials did not apply - fix the headers.
Empty
data: []
from a sane-looking filter
The value did not resolve to a real ID. Look it up via
/reference/filters/{key}/values
.
429 Too Many Requests
Rate limit. Back off, honor
Retry-After
, cache taxonomy lookups.
504
15s query timeout. Narrow the filter or set
include_total=false
.
症状原因及修复
401 Unauthorized
令牌过期(24小时)。代码片段会自动刷新。
刷新一次后仍返回
401
密钥已停用或删除。重新生成令牌无济于事;请告知用户检查https://beta.dealroom.app/settings/api
400
错误提及
X-Client-Id
缺少必需的client-id请求头,或请求头与令牌不匹配。
400
/
UNKNOWN_FILTER
过滤器键对当前范围无效。请调用
GET /reference/filters?scope=<scope>
400
/
FILTER_VALIDATION_ERROR
枚举过滤器值不在已知集合中(
round_type
investor_type
article_type
等)。值按显示名称或代码不区分大小写匹配;请通过
GET /reference/filters/{key}/values
发现它们。
400
/
PAGINATION_DEPTH_EXCEEDED
offset + limit
超过层级深度限制(仅非M2M调用者)。请缩小过滤器范围并拆分查询,而非分页更深。
200
返回但字段为null且包含
locked[]
调用被视为匿名或免费用户。你的凭据未生效——请修复请求头。
看似合理的过滤器返回空
data: []
值未解析为真实ID。请通过
/reference/filters/{key}/values
查找。
429 Too Many Requests
速率限制。请后退,遵守
Retry-After
,缓存分类查找结果。
504
15秒查询超时。请缩小过滤器范围或设置
include_total=false

Early access: data caveat

早期访问:数据说明

This skill targets
api.beta.dealroom.app
, where data may be refreshed or partially loaded. If a single result looks off, say so honestly rather than inventing an explanation, and sanity-check the same query in the production Dealroom UI before debugging further.
本技能针对
api.beta.dealroom.app
,其中数据可能会刷新或部分加载。如果单个结果看起来异常,请如实告知,而非编造解释,并在调试前在生产环境的Dealroom UI中验证相同查询。

When the API disagrees with this skill

当API与本技能描述不符时

This is an early-access API: endpoints, filter keys, fields, response shapes, and auth details can change without notice. The live API and its docs are authoritative; this skill is not. When reality and this skill conflict, trust the API and surface the gap.
Treat these as drift signals (not normal data issues):
  • A path documented here returns
    404
    /
    405
    , or a method that worked is rejected.
  • A filter key this skill names returns
    UNKNOWN_FILTER
    on a scope where it should work.
  • The response envelope differs from what is described (e.g.
    page
    renamed, fields missing or restructured,
    data
    shape changed).
  • Valid credentials no longer authenticate (header names, audience, or token flow changed).
  • GET /reference/filters?scope=<scope>
    or the published OpenAPI spec (
    developers.beta.dealroom.co/openapi.yaml
    ) advertise endpoints/filters this skill does not mention, or omit ones it does.
When you hit one:
  1. Do not paper over it with hardcoded values, guessed keys, or silent workarounds.
  2. Confirm against the source of truth:
    GET /reference/filters?scope=<scope>
    for filters, the published OpenAPI spec (
    developers.beta.dealroom.co/openapi.yaml
    ) for paths and shapes. A one-off
    400
    /
    5xx
    or empty result is usually data, not drift; a structural mismatch is reproducible.
  3. If the live state genuinely diverges from this skill, stop and tell the user plainly, for example: "The Dealroom API now behaves differently from what the
    dealroom-early-access-api
    skill describes (
    <what changed>
    ). I verified this against
    /reference/filters
    and the published OpenAPI spec. The skill looks out of date." Then proceed using the live behavior, and recommend the user update the skill (or open a PR to
    dealroom-ai/agent-skills
    ) so it stays accurate.
这是一个早期访问API:端点、过滤器键、字段、响应结构和认证详情可能会随时更改,恕不另行通知。实时API及其文档具有权威性;本技能不具备。 当实际情况与本技能描述冲突时,请以API为准并指出差异。
将这些视为漂移信号(而非正常数据问题):
  • 此处记录的路径返回
    404
    /
    405
    ,或曾经有效的方法被拒绝。
  • 本技能提及的过滤器键在其应适用的范围中返回
    UNKNOWN_FILTER
  • 响应结构与描述不符(例如
    page
    重命名、字段缺失或重构、
    data
    结构更改)。
  • 有效的凭据不再能通过认证(请求头名称、audience或令牌流程更改)。
  • GET /reference/filters?scope=<scope>
    或已发布的OpenAPI规范(
    developers.beta.dealroom.co/openapi.yaml
    )宣传了本技能未提及的端点/过滤器,或省略了本技能提及的内容。
当遇到上述情况时:
  1. 不要用硬编码值、猜测的键或静默变通方法掩盖问题
  2. 根据事实来源确认: 过滤器请查看
    GET /reference/filters?scope=<scope>
    ,路径和结构请查看已发布的OpenAPI规范(
    developers.beta.dealroom.co/openapi.yaml
    )。一次性的
    400
    /
    5xx
    错误或空结果通常是数据问题,而非漂移;结构不匹配是可重现的。
  3. 如果实际状态确实与本技能描述不符,请直接告知用户,例如:“Dealroom API现在的行为与
    dealroom-early-access-api
    技能描述的不同(<变更内容>)。我已通过
    /reference/filters
    和已发布的OpenAPI规范验证了这一点。该技能已过时。”然后按照实际行为继续操作,并建议用户更新该技能(或向
    dealroom-ai/agent-skills
    提交PR)以保持准确性。