API Documentation

Integrate with Log My Business using our REST API and OAuth 2.0 authentication

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.

API access requires a Business plan or higher. Visit your Billing page to check your plan.

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-organizations with your access token to list all organizations the authenticated user belongs to

Quick Start

  1. Go to the Developer Portal and register a new application
  2. Choose Confidential for server-to-server access or Public for browser/mobile apps
  3. Select the API scopes your application needs
  4. Save your Client ID and Client Secret (shown only once)
  5. Use the credentials to obtain an access token
  6. Include the access token in the Authorization header 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
Access tokens expire after 1 hour. Refresh tokens are valid for 7 days.

Scopes

API Scopes

Scopes control what data your application can access. Request only the scopes you need.

Scope Description Access Level
api:customers:readView customers and their detailsRead
api:customers:writeCreate, update, and delete customersWrite
api:projects:readView projects and their detailsRead
api:projects:writeCreate, update, and delete projectsWrite
api:tasks:readView tasks and their detailsRead
api:tasks:writeCreate, update, and delete tasksWrite
api:time-entries:readView time tracking entriesRead
api:time-entries:writeCreate, update, and delete time entriesWrite
api:mileage:readView mileage tracking entriesRead
api:mileage:writeCreate, update, and delete mileage entriesWrite
api:members:readView organization members and their rolesRead
api:tags:readView tagsRead
api:tags:writeCreate, update, and delete tagsWrite
Standard OpenID Connect scopes (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

MethodEndpointScopeDescription
GET/api/organization/{orgId}/membersapi:members:readList 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

MethodEndpointScopeDescription
GET/api/customer/{orgId}api:customers:readList all customers
GET/api/customer/{orgId}/{id}api:customers:readGet customer details
POST/api/customer/{orgId}api:customers:writeCreate a customer
PUT/api/customer/{orgId}/{id}api:customers:writeUpdate a customer
DELETE/api/customer/{orgId}/{id}api:customers:writeDelete 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

MethodEndpointScopeDescription
GET/api/project/{orgId}api:projects:readList all projects
GET/api/project/{orgId}/{id}api:projects:readGet project details
POST/api/project/{orgId}api:projects:writeCreate a project
PUT/api/project/{orgId}/{id}api:projects:writeUpdate a project
DELETE/api/project/{orgId}/{id}api:projects:writeDelete a project
GET/api/project/{orgId}/{id}/usersapi:projects:readList project members
GET/api/project/{orgId}/{id}/statsapi:projects:readGet 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

MethodEndpointScopeDescription
GET/api/task/{orgId}api:tasks:readList all tasks
GET/api/task/{orgId}/{id}api:tasks:readGet task details
GET/api/task/{orgId}/kanbanapi:tasks:readGet kanban board view
POST/api/task/{orgId}api:tasks:writeCreate a task
PUT/api/task/{orgId}/{id}api:tasks:writeUpdate a task
DELETE/api/task/{orgId}/{id}api:tasks:writeDelete a task
POST/api/task/{orgId}/{id}/moveapi:tasks:writeChange task status
POST/api/task/{orgId}/{id}/assignapi:tasks:writeAssign users to task
POST/api/task/{orgId}/{id}/tags/{tagId}api:tasks:writeAdd tag to task
DELETE/api/task/{orgId}/{id}/tags/{tagId}api:tasks:writeRemove tag from task
GET/api/task/{orgId}/{id}/commentsapi:tasks:readList comments on a task
POST/api/task/{orgId}/{id}/commentsapi:tasks:writeAdd a comment to a task
PUT/api/task/{orgId}/{id}/comments/{commentId}api:tasks:writeUpdate a comment (author only)
DELETE/api/task/{orgId}/{id}/comments/{commentId}api:tasks:writeDelete 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

MethodEndpointScopeDescription
GET/api/tag/{orgId}api:tags:readList all tags
GET/api/tag/{orgId}/{id}api:tags:readGet tag details
POST/api/tag/{orgId}api:tags:writeCreate a tag
PUT/api/tag/{orgId}/{id}api:tags:writeUpdate a tag
DELETE/api/tag/{orgId}/{id}api:tags:writeDelete a tag
GET/api/tag/{orgId}/{id}/tasksapi:tags:readList tasks with this tag

Create / Update Request Body

{
  "name": "Urgent",                   // required
  "color": "#EF4444",                 // required, hex color
  "description": "High priority items"
}

Time Entries

MethodEndpointScopeDescription
GET/api/timeentry/{orgId}/weekapi:time-entries:readGet weekly time view
GET/api/timeentry/{orgId}/dayapi:time-entries:readGet daily time view
GET/api/timeentry/{orgId}/reportapi:time-entries:readGet time report
POST/api/timeentry/{orgId}api:time-entries:writeCreate a time entry
PUT/api/timeentry/{orgId}/{id}api:time-entries:writeUpdate a time entry
DELETE/api/timeentry/{orgId}/{id}api:time-entries:writeDelete 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

MethodEndpointScopeDescription
GET/api/mileage/{orgId}api:mileage:readList mileage entries
GET/api/mileage/{orgId}/{id}api:mileage:readGet mileage entry details
POST/api/mileage/{orgId}api:mileage:writeCreate a mileage entry
PUT/api/mileage/{orgId}/{id}api:mileage:writeUpdate a mileage entry
DELETE/api/mileage/{orgId}/{id}api:mileage:writeDelete 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

CodeMeaningDescription
200OKRequest succeeded
201CreatedResource created successfully
400Bad RequestInvalid request body or parameters
401UnauthorizedMissing or invalid access token
403ForbiddenToken lacks required scope or organization access
404Not FoundResource does not exist
500Server ErrorUnexpected server error
If you receive a 401 error, your access token may have expired. Use the refresh token to obtain a new access token.