docyrus-api-dev
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocyrus API Developer
Docyrus API 开发者指南
Integrate with the Docyrus API using (REST client) and (React auth provider). Authenticate via OAuth2 PKCE, query data sources with powerful filtering/aggregation, and consume REST endpoints.
@docyrus/api-client@docyrus/signin使用(REST客户端)和(React认证提供者)与Docyrus API集成。通过OAuth2 PKCE进行认证,使用强大的筛选/聚合功能查询数据源,并调用REST端点。
@docyrus/api-client@docyrus/signinAuthentication Quick Start
认证快速入门
React Apps — Use @docyrus/signin
React 应用 — 使用@docyrus/signin
tsx
import { DocyrusAuthProvider, useDocyrusAuth, useDocyrusClient, SignInButton } from '@docyrus/signin'
// 1. Wrap root
<DocyrusAuthProvider
apiUrl={import.meta.env.VITE_API_BASE_URL}
clientId={import.meta.env.VITE_OAUTH2_CLIENT_ID}
redirectUri={import.meta.env.VITE_OAUTH2_REDIRECT_URI}
scopes={['offline_access', 'Read.All', 'DS.ReadWrite.All', 'Users.Read']}
callbackPath="/auth/callback"
>
<App />
</DocyrusAuthProvider>
// 2. Use hooks
function App() {
const { status, signOut } = useDocyrusAuth()
const client = useDocyrusClient() // RestApiClient | null
if (status === 'loading') return <Spinner />
if (status === 'unauthenticated') return <SignInButton />
// client is ready — make API calls
const user = await client!.get('/v1/users/me')
}tsx
import { DocyrusAuthProvider, useDocyrusAuth, useDocyrusClient, SignInButton } from '@docyrus/signin'
// 1. Wrap root
<DocyrusAuthProvider
apiUrl={import.meta.env.VITE_API_BASE_URL}
clientId={import.meta.env.VITE_OAUTH2_CLIENT_ID}
redirectUri={import.meta.env.VITE_OAUTH2_REDIRECT_URI}
scopes={['offline_access', 'Read.All', 'DS.ReadWrite.All', 'Users.Read']}
callbackPath="/auth/callback"
>
<App />
</DocyrusAuthProvider>
// 2. Use hooks
function App() {
const { status, signOut } = useDocyrusAuth()
const client = useDocyrusClient() // RestApiClient | null
if (status === 'loading') return <Spinner />
if (status === 'unauthenticated') return <SignInButton />
// client is ready — make API calls
const user = await client!.get('/v1/users/me')
}Non-React / Server — Use OAuth2Client Directly
非React / 服务端 — 直接使用OAuth2Client
typescript
import { RestApiClient, OAuth2Client, OAuth2TokenManagerAdapter, BrowserOAuth2TokenStorage } from '@docyrus/api-client'
const tokenStorage = new BrowserOAuth2TokenStorage(localStorage)
const oauth2 = new OAuth2Client({
baseURL: 'https://api.docyrus.com',
clientId: 'your-client-id',
redirectUri: 'http://localhost:3000/callback',
usePKCE: true,
tokenStorage,
})
// Auth Code flow
const { url } = await oauth2.getAuthorizationUrl({ scope: 'openid offline_access Users.Read' })
window.location.href = url
// After redirect:
const tokens = await oauth2.handleCallback(window.location.href)
// Create API client with auto-refresh
const client = new RestApiClient({
baseURL: 'https://api.docyrus.com',
tokenManager: new OAuth2TokenManagerAdapter(tokenStorage, async () => {
return (await oauth2.refreshAccessToken()).accessToken
}),
})typescript
import { RestApiClient, OAuth2Client, OAuth2TokenManagerAdapter, BrowserOAuth2TokenStorage } from '@docyrus/api-client'
const tokenStorage = new BrowserOAuth2TokenStorage(localStorage)
const oauth2 = new OAuth2Client({
baseURL: 'https://api.docyrus.com',
clientId: 'your-client-id',
redirectUri: 'http://localhost:3000/callback',
usePKCE: true,
tokenStorage,
})
// Auth Code flow
const { url } = await oauth2.getAuthorizationUrl({ scope: 'openid offline_access Users.Read' })
window.location.href = url
// After redirect:
const tokens = await oauth2.handleCallback(window.location.href)
// Create API client with auto-refresh
const client = new RestApiClient({
baseURL: 'https://api.docyrus.com',
tokenManager: new OAuth2TokenManagerAdapter(tokenStorage, async () => {
return (await oauth2.refreshAccessToken()).accessToken
}),
})API Endpoints
API 端点
Data Source Items (Dynamic per tenant)
数据源项(按租户动态生成)
GET /v1/apps/{appSlug}/data-sources/{slug}/items — List with query payload
GET /v1/apps/{appSlug}/data-sources/{slug}/items/{id} — Get one
POST /v1/apps/{appSlug}/data-sources/{slug}/items — Create
PATCH /v1/apps/{appSlug}/data-sources/{slug}/items/{id} — Update
DELETE /v1/apps/{appSlug}/data-sources/{slug}/items/{id} — Delete one
DELETE /v1/apps/{appSlug}/data-sources/{slug}/items — Delete many (body: { recordIds })Endpoints exist only if the data source is defined in the tenant. Check the tenant's OpenAPI spec at .
GET /v1/api/openapi.jsonGET /v1/apps/{appSlug}/data-sources/{slug}/items — List with query payload
GET /v1/apps/{appSlug}/data-sources/{slug}/items/{id} — Get one
POST /v1/apps/{appSlug}/data-sources/{slug}/items — Create
PATCH /v1/apps/{appSlug}/data-sources/{slug}/items/{id} — Update
DELETE /v1/apps/{appSlug}/data-sources/{slug}/items/{id} — Delete one
DELETE /v1/apps/{appSlug}/data-sources/{slug}/items — Delete many (body: { recordIds })仅当租户中定义了对应数据源时,这些端点才会存在。可通过查看租户的OpenAPI规范。
GET /v1/api/openapi.jsonSystem Endpoints (Always Available)
系统端点(始终可用)
GET /v1/users — List users
POST /v1/users — Create user
GET /v1/users/me — Current user profile
PATCH /v1/users/me — Update current userGET /v1/users — List users
POST /v1/users — Create user
GET /v1/users/me — Current user profile
PATCH /v1/users/me — Update current userMaking API Calls
调用API
typescript
// List items with query payload
const items = await client.get('/v1/apps/base/data-sources/project/items', {
columns: 'name, status, record_owner(firstname,lastname)',
filters: { rules: [{ field: 'status', operator: '!=', value: 'archived' }] },
orderBy: 'created_on DESC',
limit: 50,
})
// Get single item
const item = await client.get('/v1/apps/base/data-sources/project/items/uuid-here', {
columns: 'name, description, status',
})
// Create
const newItem = await client.post('/v1/apps/base/data-sources/project/items', {
name: 'New Project',
status: 'status-enum-id',
})
// Update
await client.patch('/v1/apps/base/data-sources/project/items/uuid-here', {
name: 'Updated Name',
})
// Delete
await client.delete('/v1/apps/base/data-sources/project/items/uuid-here')typescript
// List items with query payload
const items = await client.get('/v1/apps/base/data-sources/project/items', {
columns: 'name, status, record_owner(firstname,lastname)',
filters: { rules: [{ field: 'status', operator: '!=', value: 'archived' }] },
orderBy: 'created_on DESC',
limit: 50,
})
// Get single item
const item = await client.get('/v1/apps/base/data-sources/project/items/uuid-here', {
columns: 'name, description, status',
})
// Create
const newItem = await client.post('/v1/apps/base/data-sources/project/items', {
name: 'New Project',
status: 'status-enum-id',
})
// Update
await client.patch('/v1/apps/base/data-sources/project/items/uuid-here', {
name: 'Updated Name',
})
// Delete
await client.delete('/v1/apps/base/data-sources/project/items/uuid-here')Query Payload Summary
查询负载概览
The GET items endpoint accepts a powerful query payload:
| Feature | Purpose |
|---|---|
| Select fields, expand relations |
| Nested AND/OR groups with 50+ operators (comparison, date shortcuts, user-related) |
| Full-text search across all searchable fields |
| Sort by fields with direction, including related fields |
| Pagination (default limit: 100) |
| Return total matching count alongside results |
| Aggregations: count, sum, avg, min, max with grouping |
| Computed virtual columns (simple functions, block AST, correlated subqueries) |
| Fetch related child records as nested JSON arrays |
| Cross-tab matrix queries with date range series |
| Return full objects for relation/user/enum fields instead of IDs |
For full query reference, read:
references/query-and-formulas.mdGET 项端点支持功能强大的查询负载:
| 功能 | 用途 |
|---|---|
| 选择字段、展开关联关系 |
| 嵌套的AND/OR分组,支持50+种运算符(比较、日期快捷方式、用户相关) |
| 在所有可搜索字段中进行全文搜索 |
| 按字段及方向排序,包括关联字段 |
| 分页(默认限制:100) |
| 在返回结果的同时返回匹配的总数量 |
| 聚合操作:计数、求和、平均值、最小值、最大值及分组 |
| 计算虚拟列(简单函数、块AST、关联子查询) |
| 获取相关的子记录并以嵌套JSON数组形式返回 |
| 带日期范围序列的交叉表矩阵查询 |
| 返回关联/用户/枚举字段的完整对象而非ID |
完整查询参考,请阅读:
references/query-and-formulas.mdCritical Rules
重要规则
- Always send in list/get calls. Without it, only
columnsis returned.id - Data source endpoints are dynamic — they exist only for data sources defined in the tenant.
- Use field for
idcalculations. Use the actual field slug forcount,sum,avg,min.max - Child query keys must appear in — if childQuery key is
columns, includeordersin columns.orders - Formula keys must appear in — if formula key is
columns, includetotalin columns.total - Filter by related field using syntax.
rel_{{relation_field}}/{{field}}
- 始终在列表/获取调用中传入。如果不传入,将仅返回
columns字段。id - 数据源端点是动态的 —— 仅当租户中定义了对应数据源时才存在。
- 使用字段进行
id计算。使用实际字段别名进行count、sum、avg、min计算。max - 子查询键必须出现在中 —— 如果子查询键为
columns,需在columns中包含orders。orders - 公式键必须出现在中 —— 如果公式键为
columns,需在columns中包含total。total - 按关联字段筛选 使用语法。
rel_{{relation_field}}/{{field}}
References
参考文档
Read these files when you need detailed information:
- — Full RestApiClient API, OAuth2Client (all flows: PKCE, client credentials, device code), token managers, interceptors, error classes, SSE/streaming, file upload/download, HTML to PDF, retry logic
references/api-client.md - — @docyrus/signin React provider, useDocyrusAuth/useDocyrusClient hooks, SignInButton, standalone vs iframe auth modes, env vars, module-level API client pattern
references/authentication.md - — Complete query payload reference: column syntax, all 50+ filter operators, aggregations, simple formulas, block (AST) formulas with all block kinds, subquery formulas, child queries, pivot tables, expand, allowed SQL functions, cast types, full examples
references/query-and-formulas.md
需要详细信息时,请阅读以下文件:
- —— 完整的RestApiClient API、OAuth2Client(所有流程:PKCE、客户端凭证、设备码)、令牌管理器、拦截器、错误类、SSE/流、文件上传/下载、HTML转PDF、重试逻辑
references/api-client.md - —— @docyrus/signin React提供者、useDocyrusAuth/useDocyrusClient钩子、SignInButton、独立模式与iframe认证模式、环境变量、模块级API客户端模式
references/authentication.md - —— 完整的查询负载参考:列语法、所有50+种筛选运算符、聚合、简单公式、所有块类型的块(AST)公式、子查询公式、子查询、数据透视表、展开、允许的SQL函数、类型转换、完整示例
references/query-and-formulas.md