Full Scoro API v2 integration for OpenClaw. Provides task management, time tracking, hours calculation, utilization reports, team dashboards, and billable status corrections.
https://yourcompany.scoro.com/api/v2).json
{
"env": {
"vars": {
"SCORO_API_KEY": "ScoroAPI_your_key_here",
"SCORO_COMPANY_URL": "https://yourcompany.scoro.com/api/v2"
}
}
}
"scoro" to your agent's skills list in openclaw.json.Users can trigger these capabilities with natural language:
fetch my scoro tasks / show my tasks for this weekfetch tasks for <user email or name>show overdue tasksshow my hours this week / how many hours have I logged?calculate my billable hours / show billable vs non-billable hourssend me a report of my billable and non-billable hoursshow time entries for <user> from <date> to <date>show team status / team pulsegenerate team hours reportgenerate weekly utilization reportshow billable ratio for <user>find incorrect billable entriesfix billable status for entries <IDs>adjust all logs on task X to be billableSCORO_COMPANY_URL — full base URL (e.g. https://yourcompany.scoro.com/api/v2)SCORO_API_KEY — company API key (starts with ScoroAPI_)Both must be set in openclaw.json under env.vars. They are available as shell environment variables. Do NOT use .env files.
All Scoro API v2 requests are POST. Every request body must include apiKey and company_account_id.
The company_account_id is the subdomain from your Scoro URL. For https://yourcompany.scoro.com, it is yourcompany.
bash
curl -X POST "$SCORO_COMPANY_URL/timeEntries/list" \
-H "Content-Type: application/json" \
-d '{
"apiKey": "'"$SCORO_API_KEY"'",
"company_account_id": "yourcompany",
"filter": {
"time_entry_date": {
"from": "2026-03-10",
"to": "2026-03-16"
},
"user_ids": [123]
},
"per_page": 100,
"page": 1,
"detailed_response": true
}'
powershell
$body = @{
apiKey = $env:SCORO_API_KEY
company_account_id = 'yourcompany'
filter = @{
time_entry_date = @{ from = '2026-03-10'; to = '2026-03-16' }
user_ids = @(123)
}
per_page = 100
page = 1
detailed_response = $true
} | ConvertTo-Json -Depth 10
$response = Invoke-RestMethod -Method Post `
-Uri "$env:SCORO_COMPANY_URL/timeEntries/list" `
-ContentType 'application/json' -Body $body
All endpoints: POST $SCORO_COMPANY_URL/{module}/{action}
EndpointPurposetasks/listFetch tasks with filterstasks/view/IDView single task detailstimeEntries/listFetch time entries (with date, user, billable filters)timeEntries/modify/IDUpdate a time entry (e.g. fix billable status)users/listFetch all users (includes reporting manager info)projects/listFetch projectscontacts/listFetch contacts
json
{
"filter": {
"responsible_person_ids": [123],
"deadline": { "from": "2026-03-16", "to": "2026-03-22" },
"status": "in_progress"
}
}
responsible_person_ids — array of assigned user IDsdeadline — {"from": "YYYY-MM-DD", "to": "YYYY-MM-DD"}modified_date — {"from": "YYYY-MM-DD", "to": "YYYY-MM-DD"}CRITICAL: The date filter field is time_entry_date with from/ to keys. NOT start_date/ end_date.
json
{
"filter": {
"time_entry_date": { "from": "2026-03-10", "to": "2026-03-16" },
"user_ids": [123]
}
}
user_ids — array of user IDs (not a single value)No specific filter needed. Returns all active users.
event_id — unique task IDevent_name — task name/titledatetime_due — deadline (ISO datetime)is_completed — 0 or 1activity_type — project/category nameresponsible_person_id — assigned user IDdescription — task descriptiontime_entry_id — unique IDuser_id — the user who logged itduration — format "HH:MM:SS" (e.g. "01:30:00" = 1.5h)title — task/event namebillable_time_type — "billable", "non_billable", or "custom"time_entry_date — "YYYY-MM-DD"event_id — the task/event this entry is foris_billable — 0 or 1id — unique user IDfull_name — display nameemail — email addressposition — job titleFormat is "HH:MM:SS". Convert to decimal hours: hours + minutes/60 + seconds/3600.
Scoro caps page size at 25 items regardless of per_page setting.
You MUST paginate through ALL pages for any list operation:
text
page = 1
all_results = []
loop:
response = POST .../endpoint { per_page: 100, page: page }
if length(response.data) == 0: break
all_results += response.data
page += 1
sleep 1 second (rate limit)
Important: Do NOT use data.length < per_page as a stop condition — the API returns a max of 25 items per page even if you request 100. Stop when a page returns 0 results.
Determine date range (default: this week Monday to today)
Fetch all time entries for the date range and user(s), paginating all pages
Calculate: text
total_hours = sum(duration)
billable_hours = sum(duration where billable_time_type == "billable")
non_billable_hours = sum(duration where billable_time_type == "non_billable")
billable_ratio = (billable_hours / total_hours) * 100
Present with 2 decimal places
Teams are organized by direct manager (reporting lines).
users/list, all pages)json
POST /timeEntries/modify/<ENTRY_ID>
{
"apiKey": "...",
"company_account_id": "yourcompany",
"request": {
"billable_time_type": "billable"
}
}
Always confirm with the user before modifying entries.
json
{
"status": "OK",
"statusCode": 200,
"messages": null,
"data": []
}
tasks, timeEntries, users, projects, contacts, invoices, quotes, orders, bills, expenses, products, calendarEvents, bookings, purchaseOrders, tags, customModules, vatCodes, financeAccounts
Each module supports: list, view, modify, delete.
Use modify and delete only with explicit user permission.
apiKey and company_account_id in the JSON bodydetailed_response: true for full field data in list requestslang parameter is optional (defaults to site language)Invoke-RestMethod over curl