CompanyCam (companycam.com). Use this skill for ANY CompanyCam request — reading, creating, updating, and deleting data. Whenever a task involves CompanyCam,...
设计与多媒体
CompanyCam
试用通过托管 OAuth 接入 CompanyCam API,管理项目、照片、用户、标签、分组、文档、清单与 Webhook,所有写入操作需用户明确确认。
它能做什么
通过 Maton 网关(api.maton.ai/companycam/v2)调用 CompanyCam v2 接口,使用 Bearer Token 鉴权,OAuth 连接在 api.maton.ai/connections 管理。提供项目、照片、标签、清单、用户、分组、企业信息、协作者、Webhook 的读取与列表接口,以及项目、照片、标签、分组、用户、Webhook 的创建/更新/删除和项目文档的上传接口。分页参数为 page 与 per_page。所有创建、更新、删除、上传与 Webhook 配置都需要用户事先确认;Webhook 会把项目与照片事件推送到外部 URL,创建前必须确认目标地址与订阅事件。
什么时候用它
- 按状态或时间范围列出并筛选项目
- 为项目上传文档并打标签
- 配置项目与照片事件的 Webhook
- 管理 CompanyCam 账号的标签、分组与成员
技能文档
CompanyCam
Access the CompanyCam API with managed OAuth authentication. Manage projects, photos, users, tags, groups, documents, and webhooks for contractor photo documentation.
Quick Start
# List projects
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/companycam/v2/projects')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://api.maton.ai/companycam/v2/{resource}
Maton proxies requests to api.companycam.com/v2 and automatically injects your OAuth token.
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your CompanyCam OAuth connections at https://api.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=companycam&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
Create Connection
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'companycam'}).encode()
req = urllib.request.Request('https://api.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
Get Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2026-02-12T01:56:32.259046Z",
"last_updated_time": "2026-02-12T01:57:38.944271Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "companycam",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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
Specifying Connection
If you have multiple CompanyCam connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/companycam/v2/projects')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
Security & Permissions
- Access is scoped to projects, photos, users, tags, groups, documents, checklists, labels, collaborators, webhooks, and company info within the connected CompanyCam account.
- All write operations require explicit user approval. Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.
- Webhooks send data to external URLs. Creating a webhook causes project/photo event data to be transmitted to the specified URL. Confirm the destination URL, events, and intent with the user before creating.
- User and group management affects account membership and access. Confirm before modifying.
API Reference
Company
Get Company
GET /companycam/v2/company
Returns the current company information.
Users
Get Current User
GET /companycam/v2/users/current
List Users
GET /companycam/v2/users
Query parameters:
page- Page numberper_page- Results per page (default: 25)status- Filter by status (active, inactive)
Create User
POST /companycam/v2/users
Content-Type: application/json
{
"first_name": "John",
"last_name": "Doe",
"email_address": "john@example.com",
"user_role": "standard"
}
User roles: admin, standard, limited
Get User
GET /companycam/v2/users/{id}
Update User
PUT /companycam/v2/users/{id}
Content-Type: application/json
{
"first_name": "John",
"last_name": "Smith"
}
Delete User
DELETE /companycam/v2/users/{id}
Projects
List Projects
GET /companycam/v2/projects
Query parameters:
page- Page numberper_page- Results per page (default: 25)query- Search querystatus- Filter by statusmodified_since- Unix timestamp for filtering
Create Project
POST /companycam/v2/projects
Content-Type: application/json
{
"name": "New Construction Project",
"address": {
"street_address_1": "123 Main St",
"city": "Los Angeles",
"state": "CA",
"postal_code": "90210",
"country": "US"
}
}
Get Project
GET /companycam/v2/projects/{id}
Update Project
PUT /companycam/v2/projects/{id}
Content-Type: application/json
{
"name": "Updated Project Name"
}
Delete Project
DELETE /companycam/v2/projects/{id}
Archive Project
PATCH /companycam/v2/projects/{id}/archive
Restore Project
PUT /companycam/v2/projects/{id}/restore
Project Photos
List Project Photos
GET /companycam/v2/projects/{project_id}/photos
Query parameters:
page- Page numberper_page- Results per pagestart_date- Filter by start date (Unix timestamp)end_date- Filter by end date (Unix timestamp)user_ids- Filter by user IDsgroup_ids- Filter by group IDstag_ids- Filter by tag IDs
Add Photo to Project
POST /companycam/v2/projects/{project_id}/photos
Content-Type: application/json
{
"uri": "https://example.com/photo.jpg",
"captured_at": 1609459200,
"coordinates": {
"lat": 34.0522,
"lon": -118.2437
},
"tags": ["exterior", "front"]
}
Project Comments
List Project Comments
GET /companycam/v2/projects/{project_id}/comments
Add Project Comment
POST /companycam/v2/projects/{project_id}/comments
Content-Type: application/json
{
"comment": {
"content": "Work completed successfully"
}
}
Project Labels
List Project Labels
GET /companycam/v2/projects/{project_id}/labels
Add Labels to Project
POST /companycam/v2/projects/{project_id}/labels
Content-Type: application/json
{
"labels": ["priority", "urgent"]
}
Delete Project Label
DELETE /companycam/v2/projects/{project_id}/labels/{label_id}
Project Documents
List Project Documents
GET /companycam/v2/projects/{project_id}/documents
Upload Document
POST /companycam/v2/projects/{project_id}/documents
Content-Type: application/json
{
"uri": "https://example.com/document.pdf",
"name": "Contract.pdf"
}
Project Checklists
List Project Checklists
GET /companycam/v2/projects/{project_id}/checklists
Create Checklist from Template
POST /companycam/v2/projects/{project_id}/checklists
Content-Type: application/json
{
"checklist_template_id": "template_id"
}
Get Project Checklist
GET /companycam/v2/projects/{project_id}/checklists/{checklist_id}
Project Users
List Assigned Users
GET /companycam/v2/projects/{project_id}/assigned_users
Assign User to Project
PUT /companycam/v2/projects/{project_id}/assigned_users/{user_id}
Project Collaborators
List Collaborators
GET /companycam/v2/projects/{project_id}/collaborators
Photos
List All Photos
GET /companycam/v2/photos
Query parameters:
page- Page numberper_page- Results per page
Get Photo
GET /companycam/v2/photos/{id}
Update Photo
PUT /companycam/v2/photos/{id}
Content-Type: application/json
{
"photo": {
"captured_at": 1609459200
}
}
Delete Photo
DELETE /companycam/v2/photos/{id}
List Photo Tags
GET /companycam/v2/photos/{id}/tags
Add Tags to Photo
POST /companycam/v2/photos/{id}/tags
Content-Type: application/json
{
"tags": ["exterior", "completed"]
}
List Photo Comments
GET /companycam/v2/photos/{id}/comments
Add Photo Comment
POST /companycam/v2/photos/{id}/comments
Content-Type: application/json
{
"comment": {
"content": "Great progress!"
}
}
Tags
List Tags
GET /companycam/v2/tags
Create Tag
POST /companycam/v2/tags
Content-Type: application/json
{
"display_value": "Exterior",
"color": "#FF5733"
}
Get Tag
GET /companycam/v2/tags/{id}
Update Tag
PUT /companycam/v2/tags/{id}
Content-Type: application/json
{
"display_value": "Interior",
"color": "#3498DB"
}
Delete Tag
DELETE /companycam/v2/tags/{id}
Groups
List Groups
GET /companycam/v2/groups
Create Group
POST /companycam/v2/groups
Content-Type: application/json
{
"name": "Roofing Team"
}
Get Group
GET /companycam/v2/groups/{id}
Update Group
PUT /companycam/v2/groups/{id}
Content-Type: application/json
{
"name": "Updated Team Name"
}
Delete Group
DELETE /companycam/v2/groups/{id}
Checklists
List All Checklists
GET /companycam/v2/checklists
Query parameters:
page- Page numberper_page- Results per pagecompleted- Filter by completion status (true/false)
Webhooks
List Webhooks
GET /companycam/v2/webhooks
Create Webhook
POST /companycam/v2/webhooks
Content-Type: application/json
{
"url": "https://example.com/webhook",
"scopes": ["project.created", "photo.created"]
}
Available scopes:
project.createdproject.updatedproject.deletedphoto.createdphoto.updatedphoto.deleteddocument.createdlabel.createdlabel.deleted
Get Webhook
GET /companycam/v2/webhooks/{id}
Update Webhook
PUT /companycam/v2/webhooks/{id}
Content-Type: application/json
{
"url": "https://example.com/new-webhook",
"enabled": true
}
Delete Webhook
DELETE /companycam/v2/webhooks/{id}
Pagination
CompanyCam uses page-based pagination:
GET /companycam/v2/projects?page=2&per_page=25
Query parameters:
page- Page number (default: 1)per_page- Results per page (default: 25)
Code Examples
JavaScript - List Projects
const response = await fetch(
'https://api.maton.ai/companycam/v2/projects?per_page=10',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const projects = await response.json();
console.log(projects);
Python - List Projects
import os
import requests
response = requests.get(
'https://api.maton.ai/companycam/v2/projects',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
params={'per_page': 10}
)
projects = response.json()
for project in projects:
print(f"{project['name']}: {project['id']}")
Python - Create Project with Photo
import os
import requests
headers = {'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
base_url = 'https://api.maton.ai/companycam/v2'
# Create project
project_response = requests.post(
f'{base_url}/projects',
headers=headers,
json={
'name': 'Kitchen Renovation',
'address': {
'street_address_1': '456 Oak Ave',
'city': 'Denver',
'state': 'CO',
'postal_code': '80202',
'country': 'US'
}
}
)
project = project_response.json()
print(f"Created project: {project['id']}")
# Add photo to project
photo_response = requests.post(
f'{base_url}/projects/{project["id"]}/photos',
headers=headers,
json={
'uri': 'https://example.com/kitchen-before.jpg',
'tags': ['before', 'kitchen']
}
)
photo = photo_response.json()
print(f"Added photo: {photo['id']}")
Notes
- Project IDs and other IDs are returned as strings
- Timestamps are Unix timestamps (seconds since epoch)
- Photos can be added via URL (uri parameter)
- Comments must be wrapped in a
commentobject - Webhooks use
scopesparameter (notevents) - User roles:
admin,standard,limited - IMPORTANT: When using curl commands, use
curl -gwhen URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to
jq, environment variables may not expand correctly. Use Python examples instead.
Rate Limits
| Operation | Limit |
|---|---|
| GET requests | 240 per minute |
| POST/PUT/DELETE | 100 per minute |
When rate limited, the API returns a 429 status code. Implement exponential backoff for retries.
Error Handling
| Status | Meaning |
|---|---|
| 400 | Bad request or missing CompanyCam connection |
| 401 | Invalid or missing Maton API key |
| 404 | Resource not found |
| 422 | Validation error (check error messages) |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from CompanyCam API |
Troubleshooting: API Key Issues
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
companycam. For example:
- Correct:
https://api.maton.ai/companycam/v2/projects - Incorrect:
https://api.maton.ai/v2/projects
Resources
常见问题
- 认证方式是怎样的?
- 请求头携带 MATON_API_KEY 作为 Bearer Token;与 CompanyCam 的 OAuth 连接通过 api.maton.ai/connections 列表、创建与删除,多账号场景可用 Maton-Connection 头指定连接。
- 写入操作会自动执行吗?
- 不会。所有创建、更新、删除、上传与 Webhook 配置都需要用户事先确认;由于事件会发往外部地址,Webhook 目标 URL 也必须先与用户确认。
- 能访问哪些资源?
- 当前 CompanyCam 账号内的项目、照片、用户、标签、分组、文档、清单、标签、协作者、Webhook 与企业信息。
相关技能
通过 Maton 网关以托管 OAuth 方式访问 Basecamp 4,管理项目、待办、日程、留言、文档与团队聊天。
通过托管 OAuth 管理 ActiveCampaign 联系人、商机、自动化与营销活动,所有写入操作均需用户确认。
通过托管 OAuth 连接 Motion API,管理任务、项目、循环任务和工作区。
通过托管 OAuth 代理对接 Asana API,统一处理任务、项目、空间、用户与 Webhook。
通过托管 OAuth 访问 HubSpot CRM API,管理联系人、公司、商机及对象关联。