介绍
# Jobber
通过托管的 OAuth 身份验证访问 Jobber API。管理现场服务业务的客户、工作、发票、报价单、房产和团队成员。
## 快速开始
```bash # Get account information python <<'EOF' import urllib.request, os, json query = '{"query": "{ account { id name } }"}' req = urllib.request.Request('https://gateway.maton.ai/jobber/graphql', data=query.encode(), method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
## API 类型
Jobber 专门使用 **GraphQL API**。所有请求都是发往 `/graphql` 端点的 POST 请求,请求体为包含 `query` 字段的 JSON。
## 基础 URL
``` https://gateway.maton.ai/jobber/graphql ```
网关将请求代理到 `api.getjobber.com/api/graphql`,并自动注入您的 OAuth 令牌和 API 版本标头。
## 身份验证
所有请求都需要在 Authorization 标头中包含 Maton API 密钥:
``` Authorization: Bearer $MATON_API_KEY ```
网关会自动注入 `X-JOBBER-GRAPHQL-VERSION` 标头(目前为 `2025-04-16`)。
**环境变量:** 将您的 API 密钥设置为 `MATON_API_KEY`:
```bash export MATON_API_KEY="YOUR_API_KEY" ```
### 获取 API 密钥
1. 在 [maton.ai](https://maton.ai) 登录或创建账户 2. 前往 [maton.ai/settings](https://maton.ai/settings) 3. 复制您的 API 密钥
## 连接管理
在 `https://ctrl.maton.ai` 管理您的 Jobber OAuth 连接。
### 列出连接
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=jobber&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### 创建连接
```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'jobber'}).encode() req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### 获取连接
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**响应:** ```json { "connection": { "connection_id": "cc61da85-8bf7-4fbc-896b-4e4eb9a5aafd", "status": "ACTIVE", "creation_time": "2026-02-07T09:29:19.946291Z", "last_updated_time": "2026-02-07T09:30:59.990084Z", "url": "https://connect.maton.ai/?session_token=...", "app": "jobber", "metadata": {} } } ```
在浏览器中打开返回的 `url` 以完成 OAuth 授权。
### 删除连接
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### 指定连接
如果您有多个 Jobber 连接,请使用 `Maton-Connection` 标头指定要使用的连接:
```bash python <<'EOF' import urllib.request, os, json query = '{"query": "{ account { id name } }"}' req = urllib.request.Request('https://gateway.maton.ai/jobber/graphql', data=query.encode(), method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('Maton-Connection', 'cc61da85-8bf7-4fbc-896b-4e4eb9a5aafd') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
如果省略,网关将使用默认(最旧的)活动连接。
## API 参考
### 账户操作
#### 获取账户信息
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "{ account { id name } }" } ```
### 客户操作
#### 列出客户
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "{ clients(first: 20) { nodes { id name emails { primary address } phones { primary number } } pageInfo { hasNextPage endCursor } } }" } ```
#### 通过 ID 获取客户
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "query($id: EncodedId!) { client(id: $id) { id name emails { primary address } phones { primary number } billingAddress { street city } } }", "variables": { "id": "CLIENT_ID" } } ```
#### 创建客户
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "mutation($input: ClientCreateInput!) { clientCreate(input: $input) { client { id name } userErrors { message path } } }", "variables": { "input": { "firstName": "John", "lastName": "Doe", "email": "[email protected]", "phone": "555-1234" } } } ```
#### 更新客户
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "mutation($id: EncodedId!, $input: ClientUpdateInput!) { clientUpdate(clientId: $id, input: $input) { client { id name } userErrors { message path } } }", "variables": { "id": "CLIENT_ID", "input": { "email": "[email protected]" } } } ```
### 工作操作
#### 列出工作
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "{ jobs(first: 20) { nodes { id title jobNumber jobStatus client { name } } pageInfo { hasNextPage endCursor } } }" } ```
#### 通过 ID 获取工作
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "query($id: EncodedId!) { job(id: $id) { id title jobNumber jobStatus instructions client { name } property { address { street city } } } }", "variables": { "id": "JOB_ID" } } ```
#### 创建工作
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "mutation($input: JobCreateInput!) { jobCreate(input: $input) { job { id jobNumber title } userErrors { message path } } }", "variables": { "input": { "clientId": "CLIENT_ID", "title": "Lawn Maintenance", "instructions": "Weekly lawn care service" } } } ```
### 发票操作
#### 列出发票
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "{ invoices(first: 20) { nodes { id invoiceNumber subject total invoiceStatus client { name } } pageInfo { hasNextPage endCursor } } }" } ```
#### 通过 ID 获取发票
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "query($id: EncodedId!) { invoice(id: $id) { id invoiceNumber subject total amountDue invoiceStatus lineItems { nodes { name quantity unitPrice } } } }", "variables": { "id": "INVOICE_ID" } } ```
#### 创建发票
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "mutation($input: InvoiceCreateInput!) { invoiceCreate(input: $input) { invoice { id invoiceNumber } userErrors { message path } } }", "variables": { "input": { "clientId": "CLIENT_ID", "subject": "Service Invoice", "lineItems": [ { "name": "Lawn Care", "quantity": 1, "unitPrice": 75.00 } ] } } } ```
### 报价单操作
#### 列出报价单
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "{ quotes(first: 20) { nodes { id quoteNumber title quoteStatus client { name } } pageInfo { hasNextPage endCursor } } }" } ```
#### 创建报价单
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "mutation($input: QuoteCreateInput!) { quoteCreate(input: $input) { quote { id quoteNumber } userErrors { message path } } }", "variables": { "input": { "clientId": "CLIENT_ID", "title": "Landscaping Quote", "lineItems": [ { "name": "Garden Design", "quantity": 1, "unitPrice": 500.00 } ] } } } ```
### 房产操作
#### 列出房产
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "{ properties(first: 20) { nodes { id address { street city state postalCode } client { name } } pageInfo { hasNextPage endCursor } } }" } ```
### 请求操作
#### 列出请求
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "{ requests(first: 20) { nodes { id title requestStatus client { name } } pageInfo { hasNextPage endCursor } } }" } ```
### 用户/团队操作
#### 列出用户
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "{ users(first: 50) { nodes { id name { full } email { raw } } } }" } ```
### 自定义字段操作
#### 列出自定义字段
```bash POST /jobber/graphql Content-Type: application/json
{ "query": "{ customFields(first: 50) { nodes { id name fieldType } } }" } ```
## 分页
Jobber 使用 Relay 风格的基于光标的分页:
```bash # First page POST /jobber/graphql { "query": "{ clients(first: 20) { nodes { id name } pageInfo { hasNextPage endCursor } } }" }
# Next page using cursor POST /jobber/graphql { "query": "{ clients(first: 20, after: \"CURSOR_VALUE\") { nodes { id name } pageInfo { hasNextPage endCursor } } }" } ```
响应包含 `pageInfo`: ```json { "data": { "clients": { "nodes": [...], "pageInfo": { "hasNextPage": true, "endCursor": "abc123" } } } } ```
## Webhooks
Jobber 支持 Webhooks 以实现实时事件通知:
- `CLIENT_CREATE` - 创建了新客户 - `JOB_COMPLETE` - 工作标记为完成 - `QUOTE_CREATE` - 创建了新报价单 - `QUOTE_APPROVAL` - 报价单已批准 - `REQUEST_CREATE` - 创建了新请求 - `INVOICE_CREATE` - 创建了新发票 - `APP_CONNECT` - 应用已连接
Webhooks 包含 HMAC-SHA256 签名用于验证。
## 代码示例
### JavaScript
```javascript const query = `{ clients(first: 10) { nodes { id name emails { address } } } }`;
const response = await fetch('https://gateway.maton.ai/jobber/graphql', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ query }) });
const data = await response.json(); ```
### Python
```python import os import requests
query = ''' { clients(first: 10) { nodes { id name emails { address } } } } '''
response = requests.post( 'https://gateway.maton.ai/jobber/graphql', headers={ 'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}', 'Content-Type': 'application/json' }, json={'query': query} ) data = response.json() ```
## 注意事项
- Jobber 专门使用 GraphQL(没有 REST API) - 网关会自动注入 `X-JOBBER-GRAPHQL-VERSION` 标头 - 当前网关 API 版本:`2025-04-16`(最新) - 旧版 API 在发布后支持 12-18 个月 - 使用 Jobber 开发者中心中的 GraphiQL 浏览器进行架构发现 - ID 使用 `EncodedId` 类型(base64 编码)- 以字符串形式传递 - 字段命名:使用 `emails`/`phones`(数组)、`jobStatus`/`invoiceStatus`/`quoteStatus`/`requestStatus` - 速率限制: - DDoS 防护:每个应用/账户每 5 分钟 2,500 个请求 - 查询成本:使用漏桶算法基于点数(最大 10,000 点,每秒恢复 500 点) - 避免深度嵌套查询以降低查询成本 - 重要提示:将 curl 输出通过管道传递给 `jq` 或其他命令时,`$MATON_API_KEY` 等环境变量在某些 Shell 环境中可能无法正确展开
## 错误处理
| 状态 | 含义 | |--------|---------| | 400 | 缺少 Jobber 连接或查询格式错误 | | 401 | Maton API 密钥无效或缺失 | | 403 | 未授权(请检查 OAuth 范围) | | 429 | 速率受限 | | 4xx/5xx | 来自 Jobber API 的透传错误 |
GraphQL 错误出现在响应体中: ```json { "errors": [ { "message": "Error description", "locations": [...], "path": [...] } ] } ```
变更错误出现在 `userErrors` 中: ```json { "data": { "clientCreate": { "client": null, "userErrors": [ { "message": "Email is required", "path": ["input", "email"] } ] } } } ```
### 故障排除:API 密钥问题
1. 检查是否设置了 `MATON_API_KEY` 环境变量:
```bash echo $MATON_API_KEY ```
2. 通过列出连接来验证 API 密钥是否有效:
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### 故障排除:无效的应用名称
1. 确保您的 URL 路径以 `jobber` 开头。例如:
- 正确:`https://gateway.maton.ai/jobber/graphql` - 错误:`https://gateway.maton.ai/graphql`
## 资源
- [Jobber 开发者文档](https://developer.getjobber.com/docs/) - [入门指南](https://developer.getjobber.com/docs/getting_started/) - [API 支持](mailto:[email protected]) - [Maton 社区](https://discord.com/invite/dBfFAcefs2) - [Maton 支持](mailto:[email protected])