API Documentation
Getting Started
Overview
The Log My Business API allows third-party applications to access and manage organization data including customers, projects, tasks, time entries, and mileage records. All API endpoints are scoped to an organization and require proper authentication.
Base URL
https://app.logmybusiness.com/api
Organization ID
All API endpoints require your Organization ID in the path. You can find it in two places:
- The Developer Portal displays your Organization ID at the top of the page
-
Authorization Code flow only: Call
GET /api/organization/my-organizationswith your access token to list all organizations the authenticated user belongs to
Quick Start
- Go to the Developer Portal and register a new application
- Choose Confidential for server-to-server access or Public for browser/mobile apps
- Select the API scopes your application needs
- Save your Client ID and Client Secret (shown only once)
- Use the credentials to obtain an access token
- Include the access token in the
Authorizationheader of your API requests
Two Authentication Flows
Client Credentials (Server-to-Server)
For backend services that need to access organization data without user interaction. The token acts on behalf of the organization, not a specific user.
Best for: cron jobs, data sync, reporting tools, backend integrations
Authorization Code + PKCE (User-Delegated)
For applications that need to act on behalf of a specific user. The user authorizes the application via a consent screen, and the token carries their identity and permissions.
Best for: web apps, mobile apps, third-party dashboards
Authentication
Client Credentials Flow
Exchange your client credentials for an access token. Requires a confidential client.
Request
POST /connect/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=api:customers:read api:projects:read
Response
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600
}
Authorization Code + PKCE Flow
For applications that need user-delegated access. Works with both public and confidential clients.
Step 1: Redirect user to authorize
GET /connect/authorize?
client_id=YOUR_CLIENT_ID
&response_type=code
&redirect_uri=https://your-app.com/callback
&scope=openid email profile api:customers:read
&code_challenge=YOUR_PKCE_CHALLENGE
&code_challenge_method=S256
The user will see a consent screen listing the requested permissions. After approving, they'll be
redirected to your redirect_uri with an authorization code.
Step 2: Exchange code for token
POST /connect/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=YOUR_CLIENT_ID
&code=AUTHORIZATION_CODE
&redirect_uri=https://your-app.com/callback
&code_verifier=YOUR_PKCE_VERIFIER
Response
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJSUzI1NiIs...",
"id_token": "eyJhbGciOiJSUzI1NiIs..."
}
Refreshing Tokens
POST /connect/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&client_id=YOUR_CLIENT_ID
&refresh_token=YOUR_REFRESH_TOKEN
Using Access Tokens
Include the access token in the Authorization header of every API request:
GET /api/customer/{organizationId}
Authorization: Bearer YOUR_ACCESS_TOKEN
Scopes
API Scopes
Scopes control what data your application can access. Request only the scopes you need.
| Scope | Description | Access Level |
|---|---|---|
api:customers:read | View customers and their details | Read |
api:customers:write | Create, update, and delete customers | Write |
api:projects:read | View projects and their details | Read |
api:projects:write | Create, update, and delete projects | Write |
api:tasks:read | View tasks and their details | Read |
api:tasks:write | Create, update, and delete tasks | Write |
api:time-entries:read | View time tracking entries | Read |
api:time-entries:write | Create, update, and delete time entries | Write |
api:mileage:read | View mileage tracking entries | Read |
api:mileage:write | Create, update, and delete mileage entries | Write |
api:members:read | View organization members and their roles | Read |
api:tags:read | View tags | Read |
api:tags:write | Create, update, and delete tags | Write |
openid, email, profile)
are also available for Authorization Code flow to access user identity information.
Endpoints
All endpoints require authentication and are scoped to an organization via the
{organizationId} path parameter. Abbreviated as {orgId} below.
Organization Members
| Method | Endpoint | Scope | Description |
|---|---|---|---|
| GET | /api/organization/{orgId}/members | api:members:read | List organization members |
Response
[
{
"userId": "abc-123",
"email": "user@example.com",
"displayName": "Jane Smith",
"firstName": "Jane",
"lastName": "Smith",
"role": "Admin",
"joinedAt": "2025-06-15T10:30:00Z"
}
]
Customers
| Method | Endpoint | Scope | Description |
|---|---|---|---|
| GET | /api/customer/{orgId} | api:customers:read | List all customers |
| GET | /api/customer/{orgId}/{id} | api:customers:read | Get customer details |
| POST | /api/customer/{orgId} | api:customers:write | Create a customer |
| PUT | /api/customer/{orgId}/{id} | api:customers:write | Update a customer |
| DELETE | /api/customer/{orgId}/{id} | api:customers:write | Delete a customer |
Create / Update Request Body
{
"name": "Acme Corp", // required
"companyName": "Acme Corporation",
"email": "contact@acme.com",
"phoneNumber": "555-0100",
"addressLine1": "123 Main St",
"city": "Springfield",
"stateProvince": "IL",
"postalCode": "62704",
"country": "US",
"customerType": "Business",
"status": "Active",
"notes": "Key account",
"creditLimit": 10000.00
}
Projects
| Method | Endpoint | Scope | Description |
|---|---|---|---|
| GET | /api/project/{orgId} | api:projects:read | List all projects |
| GET | /api/project/{orgId}/{id} | api:projects:read | Get project details |
| POST | /api/project/{orgId} | api:projects:write | Create a project |
| PUT | /api/project/{orgId}/{id} | api:projects:write | Update a project |
| DELETE | /api/project/{orgId}/{id} | api:projects:write | Delete a project |
| GET | /api/project/{orgId}/{id}/users | api:projects:read | List project members |
| GET | /api/project/{orgId}/{id}/stats | api:projects:read | Get project statistics |
Create / Update Request Body
{
"name": "Website Redesign", // required
"customerId": 1, // optional, link to customer
"description": "Full site overhaul",
"status": "Active",
"projectCode": "WEB-001",
"hourlyRate": 150.00,
"isBillable": true,
"startDate": "2025-01-15",
"endDate": "2025-06-30",
"budgetAmount": 50000.00
}
Tasks
| Method | Endpoint | Scope | Description |
|---|---|---|---|
| GET | /api/task/{orgId} | api:tasks:read | List all tasks |
| GET | /api/task/{orgId}/{id} | api:tasks:read | Get task details |
| GET | /api/task/{orgId}/kanban | api:tasks:read | Get kanban board view |
| POST | /api/task/{orgId} | api:tasks:write | Create a task |
| PUT | /api/task/{orgId}/{id} | api:tasks:write | Update a task |
| DELETE | /api/task/{orgId}/{id} | api:tasks:write | Delete a task |
| POST | /api/task/{orgId}/{id}/move | api:tasks:write | Change task status |
| POST | /api/task/{orgId}/{id}/assign | api:tasks:write | Assign users to task |
| POST | /api/task/{orgId}/{id}/tags/{tagId} | api:tasks:write | Add tag to task |
| DELETE | /api/task/{orgId}/{id}/tags/{tagId} | api:tasks:write | Remove tag from task |
| GET | /api/task/{orgId}/{id}/comments | api:tasks:read | List comments on a task |
| POST | /api/task/{orgId}/{id}/comments | api:tasks:write | Add a comment to a task |
| PUT | /api/task/{orgId}/{id}/comments/{commentId} | api:tasks:write | Update a comment (author only) |
| DELETE | /api/task/{orgId}/{id}/comments/{commentId} | api:tasks:write | Delete a comment (author, Admin, or Owner) |
Create Request Body
{
"title": "Design homepage mockup", // required
"projectId": 1, // required
"description": "Create initial wireframes",
"priority": 2, // 0=Low, 1=Medium, 2=High, 3=Critical
"dueDate": "2025-02-28",
"startDate": "2025-02-01",
"estimatedHours": 8.0,
"assigneeIds": ["user-id-1", "user-id-2"],
"tagIds": [1, 3]
}
Update Request Body (all fields optional)
{
"title": "Updated title",
"status": "InProgress", // Todo, InProgress, Review, Done
"priority": 3, // 0=Low, 1=Medium, 2=High, 3=Critical
"progress": 50,
"actualHours": 4.5
}
Comment Request Body (POST / PUT)
{
"comment": "Looks good — ready for review" // required, max 5000 chars
}
Comment Response
{
"id": 42,
"taskId": 5,
"userId": "abc-123",
"userName": "Jane Smith",
"profilePictureUrl": null,
"comment": "Looks good — ready for review",
"createdAt": "2026-05-05T14:22:00Z",
"updatedAt": null,
"isSystemGenerated": false
}
Tags
| Method | Endpoint | Scope | Description |
|---|---|---|---|
| GET | /api/tag/{orgId} | api:tags:read | List all tags |
| GET | /api/tag/{orgId}/{id} | api:tags:read | Get tag details |
| POST | /api/tag/{orgId} | api:tags:write | Create a tag |
| PUT | /api/tag/{orgId}/{id} | api:tags:write | Update a tag |
| DELETE | /api/tag/{orgId}/{id} | api:tags:write | Delete a tag |
| GET | /api/tag/{orgId}/{id}/tasks | api:tags:read | List tasks with this tag |
Create / Update Request Body
{
"name": "Urgent", // required
"color": "#EF4444", // required, hex color
"description": "High priority items"
}
Time Entries
| Method | Endpoint | Scope | Description |
|---|---|---|---|
| GET | /api/timeentry/{orgId}/week | api:time-entries:read | Get weekly time view |
| GET | /api/timeentry/{orgId}/day | api:time-entries:read | Get daily time view |
| GET | /api/timeentry/{orgId}/report | api:time-entries:read | Get time report |
| POST | /api/timeentry/{orgId} | api:time-entries:write | Create a time entry |
| PUT | /api/timeentry/{orgId}/{id} | api:time-entries:write | Update a time entry |
| DELETE | /api/timeentry/{orgId}/{id} | api:time-entries:write | Delete a time entry |
Create / Update Request Body
{
"projectId": 1, // required
"date": "2025-02-15", // required
"hours": 4.5, // required, 0.01-24
"categoryId": 2, // optional project category
"taskId": 5, // optional link to task
"description": "Frontend work",
"startTime": "09:00:00", // optional
"endTime": "13:30:00" // optional
}
Mileage
| Method | Endpoint | Scope | Description |
|---|---|---|---|
| GET | /api/mileage/{orgId} | api:mileage:read | List mileage entries |
| GET | /api/mileage/{orgId}/{id} | api:mileage:read | Get mileage entry details |
| POST | /api/mileage/{orgId} | api:mileage:write | Create a mileage entry |
| PUT | /api/mileage/{orgId}/{id} | api:mileage:write | Update a mileage entry |
| DELETE | /api/mileage/{orgId}/{id} | api:mileage:write | Delete a mileage entry |
Create Request Body
{
"projectId": 1, // required
"date": "2025-02-15", // required
"totalMiles": 45.2, // required
"startMiles": 12500.0, // optional, odometer start
"endMiles": 12545.2, // optional, odometer end
"mileageRate": 0.67, // optional, override default
"description": "Client site visit",
"isBillable": true
}
Errors
Error Handling
The API uses standard HTTP status codes to indicate success or failure.
Error Response Format
{
"message": "A human-readable error description"
}
HTTP Status Codes
| Code | Meaning | Description |
|---|---|---|
200 | OK | Request succeeded |
201 | Created | Resource created successfully |
400 | Bad Request | Invalid request body or parameters |
401 | Unauthorized | Missing or invalid access token |
403 | Forbidden | Token lacks required scope or organization access |
404 | Not Found | Resource does not exist |
500 | Server Error | Unexpected server error |
401 error, your access token may have expired.
Use the refresh token to obtain a new access token.