Jobber
2026-03-27
新闻来源:网淘吧
围观:14
电脑广告
手机广告
Jobber
通过托管的 OAuth 认证访问 Jobber API。为现场服务企业管理客户、工作、发票、报价、物业和团队成员。
快速入门
# 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 请求,请求体为 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:
export MATON_API_KEY="YOUR_API_KEY"
获取您的API密钥
复制您的API密钥
连接管理在https://ctrl.maton.ai
管理您的Jobber OAuth连接
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
。
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
列出连接
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
创建连接
{
"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
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
以完成OAuth授权。
如果您有多个Jobber连接,请使用Maton-Connection标头来指定要使用哪一个:
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参考
账户操作
获取账户信息
POST /jobber/graphql
Content-Type: application/json
{
"query": "{ account { id name } }"
}
客户操作
列出客户
POST /jobber/graphql
Content-Type: application/json
{
"query": "{ clients(first: 20) { nodes { id name emails { primary address } phones { primary number } } pageInfo { hasNextPage endCursor } } }"
}
通过ID获取客户
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" }
}
创建客户
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": "john@example.com",
"phone": "555-1234"
}
}
}
更新客户
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": "newemail@example.com"
}
}
}
任务操作
列出任务
POST /jobber/graphql
Content-Type: application/json
{
"query": "{ jobs(first: 20) { nodes { id title jobNumber jobStatus client { name } } pageInfo { hasNextPage endCursor } } }"
}
通过ID获取任务
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" }
}
创建任务
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"
}
}
}
发票操作
列出发票
POST /jobber/graphql
Content-Type: application/json
{
"query": "{ invoices(first: 20) { nodes { id invoiceNumber subject total invoiceStatus client { name } } pageInfo { hasNextPage endCursor } } }"
}
通过ID获取发票
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" }
}
创建发票
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
}
]
}
}
}
报价单操作
列出报价单
POST /jobber/graphql
Content-Type: application/json
{
"query": "{ quotes(first: 20) { nodes { id quoteNumber title quoteStatus client { name } } pageInfo { hasNextPage endCursor } } }"
}
创建报价单
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
}
]
}
}
}
物业操作
列出属性
POST /jobber/graphql
Content-Type: application/json
{
"query": "{ properties(first: 20) { nodes { id address { street city state postalCode } client { name } } pageInfo { hasNextPage endCursor } } }"
}
请求操作
列出请求
POST /jobber/graphql
Content-Type: application/json
{
"query": "{ requests(first: 20) { nodes { id title requestStatus client { name } } pageInfo { hasNextPage endCursor } } }"
}
用户/团队操作
列出用户
POST /jobber/graphql
Content-Type: application/json
{
"query": "{ users(first: 50) { nodes { id name { full } email { raw } } } }"
}
自定义字段操作
列出自定义字段
POST /jobber/graphql
Content-Type: application/json
{
"query": "{ customFields(first: 50) { nodes { id name fieldType } } }"
}
分页
Jobber 采用 Relay 风格的基于游标的分页:
# 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 } } }"
}
响应包含页面信息:
{
"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
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
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/电话(数组),工作状态/发票状态/报价状态/请求状态 - 速率限制:
- 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错误会显示在响应体中:
{
"errors": [
{
"message": "Error description",
"locations": [...],
"path": [...]
}
]
}
变更操作错误会出现在userErrors字段中:
{
"data": {
"clientCreate": {
"client": null,
"userErrors": [
{
"message": "Email is required",
"path": ["input", "email"]
}
]
}
}
}
故障排除:API密钥问题
- 检查是否已设置
MATON_API_KEY环境变量:
echo $MATON_API_KEY
- 通过列出连接来验证API密钥是否有效:
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
故障排除:应用名称无效
- 请确保您的URL路径以
jobber开头。例如:
- 正确示例:
https://gateway.maton.ai/jobber/graphql - 不正确:
https://gateway.maton.ai/graphql
资源
文章底部电脑广告
手机广告位-内容正文底部
上一篇:TickTick CLI
下一篇:Feishu Docx PowerWrite


微信扫一扫,打赏作者吧~