Download OpenAPI specification:
MinuteDock is a time tracking and invoicing application for small businesses. This API allows you to manage time entries, contacts, projects, tasks, and generate reports.
All MinuteDock API endpoints require authentication. This section covers everything you need to know about authenticating with the API.
Every request must include your API key in the X-API-Key header:
curl -H "X-API-Key: your-api-key" https://minutedock.com/api/v1/users/me
To get your API key:
MinuteDock supports multiple accounts per user. By default, the API uses your currently active account. To work with a specific account, include the X-Account-ID header:
curl -H "X-API-Key: your-api-key" \
-H "X-Account-ID: 12345" \
https://minutedock.com/api/v1/entries
We strongly recommend always specifying the X-Account-ID header to ensure consistency, especially if you belong to multiple accounts.
To determine which accounts you have access to:
GET /accountsGET /accounts/currentBasic authenticated request:
curl -H "X-API-Key: abc123def456" \
https://minutedock.com/api/v1/users/me
Request with specific account:
curl -H "X-API-Key: abc123def456" \
-H "X-Account-ID: 789" \
https://minutedock.com/api/v1/contacts
Creating an entry with authentication:
curl -X POST \
-H "X-API-Key: abc123def456" \
-H "X-Account-ID: 789" \
-H "Content-Type: application/json" \
-d '{"entry": {"description": "Client meeting", "duration": 3600}}' \
https://minutedock.com/api/v1/entries
For POST/PUT requests, use application/json with parameters nested under the resource name:
curl -X POST -H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{"entry": {"description": "Meeting with client", "duration": 3600}}' \
https://minutedock.com/api/v1/entries
API requests are rate limited. If you exceed the limit, you'll receive a 429 status code.
Important: This API contains legacy fields that can be confusing. Please read this section carefully.
Historically, users could only belong to one MinuteDock account, so a simple user_id field was sufficient.
When we introduced multi-account support (allowing users to belong to multiple MinuteDock accounts), we added
the user_account_id field to properly identify users within specific accounts.
/users): Contain both id (legacy user ID) and user_account_id (the correct ID to use)user_id (deprecated, matches User.id) and user_account_id (correct)user_id fields that are deprecateduser_account_id - this correctly identifies users within accountsid and user_id fields - these contain legacy user IDs only for backward compatibilityIn the next major API version:
user_id fields will be removed entirelyuser_account_id field will be renamed to simply user_idReturns all users in the current account
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
[- {
- "id": "123",
- "email": "john.doe@example.com",
- "first_name": "John",
- "last_name": "Doe",
- "billing_rate": "100.00"
}, - {
- "id": "124",
- "email": "jane.smith@example.com",
- "first_name": "Jane",
- "last_name": "Smith",
- "billing_rate": "120.00"
}
]DEPRECATED: Use PUT /dock instead for timer management.
Starts the timer on a specific entry. The entry must not be logged. For new integrations, use the /dock endpoint which provides better conflict resolution and synchronization across devices.
| entryId required | integer Entry ID to start timer on |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}DEPRECATED: Use PUT /dock instead for timer management.
Pauses the timer on a specific entry. The entry must have an active timer. For new integrations, use the /dock endpoint which provides better conflict resolution and synchronization across devices.
| entryId required | integer Entry ID to pause timer on |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}Moves a logged entry back to the dock (active timer). If there's already an active timer, it will be logged first. Any insignificant time from the previous timer is added to this entry.
| entryId required | integer Entry ID to redock |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}DEPRECATED: Use GET /dock instead.
Alias for /dock - returns the current active timer entry. For new integrations, use the /dock endpoint directly.
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}Returns the current active timer entry (dock). This is the entry that's currently being tracked. Returns null if no timer is active.
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "account_id": "456",
- "user_account_id": "123",
- "description": "Working on API improvements",
- "duration": 1800,
- "duration_hours": "0.5",
- "contact_id": "789",
- "project_id": "1011",
- "task_ids": [
- "1213"
], - "logged": false,
- "timer_active": true,
- "date": "",
- "version_id": "550e8400-e29b-41d4-a716-446655440000",
- "version_client_id": "web-app",
- "version_number": 42
}Updates the current dock entry with version control for distributed synchronization. This endpoint ensures consistency across multiple clients (web, mobile, etc.).
The version parameters are required to prevent conflicts when multiple clients are updating the timer simultaneously.
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
object |
{- "entry": {
- "id": 5433,
- "description": "Updated description for API improvements",
- "duration": 3600,
- "timer_active": false,
- "version_id": "550e8400-e29b-41d4-a716-446655440000",
- "version_client_id": "my-app",
- "version_number": 42
}
}{- "id": null,
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "invoice_id": null,
- "rate": null,
- "timer_active": true,
- "logged": false,
- "version_id": "550e8400-e29b-41d4-a716-446655440000",
- "version_client_id": "web-app",
- "version_number": 42
}Search and filter time entries. Results are sorted by date descending. Use various parameters to filter results.
| limit | integer [ 1 .. 1000 ] Default: 500 Example: limit=100 Maximum number of results to return (max 1000) |
| offset | integer >= 0 Default: 0 Number of results to skip for pagination |
(Array of strings or integers or null) (ListFilter) Example: user_accounts=all Filter by user account IDs | |
(Array of strings or integers or null) (ListFilter) Example: contacts=789,790 Filter by Contact IDs | |
(Array of strings or integers or null) (ListFilter) Example: projects=1011,1012 Filter by Project IDs | |
(Array of strings or integers or null) (ListFilter) Example: tasks=1213,1214 Filter by Task IDs | |
| from | string <date> Example: from=2024-01-01 Start date (inclusive) |
| to | string <date> Example: to=2024-01-31 End date (inclusive) |
| since | string <date-time> Example: since=2024-01-15T00:00:00Z Return entries updated after this timestamp |
| users | Array of strings Deprecated Example: users=all DEPRECATED: Use |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
[- {
- "id": "5432",
- "account_id": "456",
- "user_account_id": "123",
- "description": "API documentation review #development",
- "duration": 3600,
- "duration_hours": "1.0",
- "contact_id": "789",
- "project_id": "1011",
- "task_ids": [
- "1213"
], - "logged": true,
- "timer_active": false,
- "logged_at": "2024-01-20T14:30:00-05:00",
- "date": "2024-01-20",
- "rate": "175.00",
- "updated_at": "2024-01-20T19:30:00Z"
}
]Creates a new time entry. If no date is provided, creates an active timer. Tasks can be specified via task_ids array or by using #hashtags in the description.
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
object |
{- "entry": {
- "description": "Working on new feature #development #backend",
- "duration": 7200,
- "contact_id": 789,
- "project_id": 1011,
- "task_ids": [
- "1213",
- "1214"
], - "date": "2024-01-20"
}
}{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}Retrieve a specific entry by ID or use 'current' to get the active timer
required | integer or string Example: 5432 Entry ID or 'current' for active timer |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}Update an existing entry. You can only update your own entries unless you have admin permissions. For active timers, some fields like timer_active can control start/pause state.
required | integer or string Example: 5432 Entry ID or 'current' for active timer |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
object |
{- "entry": {
- "description": "Updated description",
- "duration": 5400,
- "task_ids": [
- 1213,
- 1215
]
}
}{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}Delete an entry. You can only delete your own entries unless you have admin permissions.
required | integer or string Example: 5432 Entry ID or 'current' for active timer |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "5432",
- "status": "deleted"
}DEPRECATED: Use PUT /dock instead for timer management.
Pauses the timer on a specific entry. The entry must have an active timer. For new integrations, use the /dock endpoint which provides better conflict resolution and synchronization across devices.
| entryId required | integer Entry ID to pause timer on |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}DEPRECATED: Use PUT /dock with logged: true instead.
Logs an entry, which stops any active timer and saves it with the current date. This action cannot be undone - to start timing again, use the redock endpoint. For new integrations, use the /dock endpoint which provides better conflict resolution and synchronization across devices.
| entryId required | integer Entry ID to log |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}Moves a logged entry back to the dock (active timer). If there's already an active timer, it will be logged first. Any insignificant time from the previous timer is added to this entry.
| entryId required | integer Entry ID to redock |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}Returns all contacts/clients in the current account
| active | boolean Filter by active status |
| pinned | boolean Filter by pinned status |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
[- {
- "id": "789",
- "name": "ABC Industries",
- "short_code": "ABC",
- "active": true,
- "pinned": true,
- "default_rate_dollars": "150.00"
}, - {
- "id": "790",
- "name": "XYZ Corp",
- "short_code": "XYZ",
- "active": true,
- "pinned": false,
- "default_rate_dollars": "125.00"
}
]Creates a new contact/client
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
object (Contact) A client/customer that time can be tracked against |
{- "contact": {
- "name": "New Client Inc",
- "short_code": "NCI",
- "active": true,
- "default_rate_dollars": "175.00"
}
}{- "id": "791",
- "name": "New Client Inc",
- "short_code": "NCI",
- "active": true,
- "pinned": false,
- "default_rate_dollars": "175.00"
}Retrieve details of a specific contact
| contactId required | integer Contact ID |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "name": "ABC Industries",
- "short_code": "ABC",
- "active": true,
- "pinned": false,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "budget_progress": 30.5,
- "default_rate_dollars": "150.00",
- "billable": true
}Update contact details
| contactId required | integer Contact ID |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
| name required | string non-empty |
| short_code | string Short code identifier for the Contact. In the application UI, time can be tracked for a Contact using this @identifier |
| active | boolean Default: true Whether the contact is active |
| pinned | boolean Default: false Whether the contact is pinned for quick access |
| budget_type | string or null Default: "null" Enum: "hours" "billable" The type of budget tracking. If not set (null), the budget will not be tracked. An 'hours' budget will track the number of hours for time entries within the budget period. A 'billable' budget will track the billable value of time entries within the budget period. |
| budget_frequency | string or null Default: "null" Enum: "total" "weekly" "monthly" "quarterly" "yearly" The time period which the budget will report on |
| budget_target | number or null Default: "null" The targetted value for the budget. For an hourly budget, this is the number of hours. For a money budget, this is the amount in dollars. |
CurrencyString (string) or null Default hourly rate for tracked time. If not set (null), the appropriate next rate will be used. A time entry's billing rate will be chosen, in order, from:
| |
| billable | boolean Default: true Whether tracked time should be billed (Rate is not 0) |
{- "id": "123456",
- "name": "ABC Industries",
- "short_code": "ABC",
- "active": true,
- "pinned": false,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "default_rate_dollars": "150.00",
- "billable": true
}{- "id": "123456",
- "name": "ABC Industries",
- "short_code": "ABC",
- "active": true,
- "pinned": false,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "budget_progress": 30.5,
- "default_rate_dollars": "150.00",
- "billable": true
}Delete a Contact. This will not delete associated time Entries.
| contactId required | integer Contact ID |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123",
- "status": "deleted"
}Returns all projects in the current account
| contact_id | integer Filter projects by contact |
| active | boolean Filter by active status |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
[- {
- "id": "123456",
- "name": "Website Redesign",
- "contact_id": "123456",
- "short_code": "ABC",
- "active": true,
- "pinned": true,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "budget_progress": 30.5,
- "default_rate_dollars": "150.00",
- "billable": true
}
]Create a new Project within a Contact
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
| name required | string non-empty |
| contact_id required | string (ID) ID of the Contact this project belongs to. A Project is always associated with a Contact. |
| short_code | string Short code identifier for the Project. In the application UI, time can be tracked for a Project using this #code |
| active | boolean Default: true Whether the project is active |
| pinned | boolean Default: false Whether the project is pinned for quick access |
| budget_type | string or null Default: "null" Enum: "hours" "billable" The type of budget tracking. If not set (null), the budget will not be tracked. An 'hours' budget will track the number of hours for time entries within the budget period. A 'billable' budget will track the billable value of time entries within the budget period. |
| budget_frequency | string or null Default: "null" Enum: "total" "weekly" "monthly" "quarterly" "yearly" The time period which the budget will report on |
| budget_target | number or null Default: "null" The targetted value for the budget. For an hourly budget, this is the number of hours. For a money budget, this is the amount in dollars. |
CurrencyString (string) or null Default hourly rate for tracked time. If not set (null), the appropriate next rate will be used. A time entry's billing rate will be chosen, in order, from:
| |
| billable | boolean Default: true Whether tracked time should be billed (Rate is not 0) |
{- "id": "123456",
- "name": "Website Redesign",
- "contact_id": "123456",
- "short_code": "ABC",
- "active": true,
- "pinned": true,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "default_rate_dollars": "150.00",
- "billable": true
}{- "id": "123456",
- "name": "Website Redesign",
- "contact_id": "123456",
- "short_code": "ABC",
- "active": true,
- "pinned": true,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "budget_progress": 30.5,
- "default_rate_dollars": "150.00",
- "billable": true
}Retrieve details of a specific Project
| projectId required | integer |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "name": "Website Redesign",
- "contact_id": "123456",
- "short_code": "ABC",
- "active": true,
- "pinned": true,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "budget_progress": 30.5,
- "default_rate_dollars": "150.00",
- "billable": true
}Update Project details
| projectId required | integer |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
| name required | string non-empty |
| contact_id required | string (ID) ID of the Contact this project belongs to. A Project is always associated with a Contact. |
| short_code | string Short code identifier for the Project. In the application UI, time can be tracked for a Project using this #code |
| active | boolean Default: true Whether the project is active |
| pinned | boolean Default: false Whether the project is pinned for quick access |
| budget_type | string or null Default: "null" Enum: "hours" "billable" The type of budget tracking. If not set (null), the budget will not be tracked. An 'hours' budget will track the number of hours for time entries within the budget period. A 'billable' budget will track the billable value of time entries within the budget period. |
| budget_frequency | string or null Default: "null" Enum: "total" "weekly" "monthly" "quarterly" "yearly" The time period which the budget will report on |
| budget_target | number or null Default: "null" The targetted value for the budget. For an hourly budget, this is the number of hours. For a money budget, this is the amount in dollars. |
CurrencyString (string) or null Default hourly rate for tracked time. If not set (null), the appropriate next rate will be used. A time entry's billing rate will be chosen, in order, from:
| |
| billable | boolean Default: true Whether tracked time should be billed (Rate is not 0) |
{- "id": "123456",
- "name": "Website Redesign",
- "contact_id": "123456",
- "short_code": "ABC",
- "active": true,
- "pinned": true,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "default_rate_dollars": "150.00",
- "billable": true
}{- "id": "123456",
- "name": "Website Redesign",
- "contact_id": "123456",
- "short_code": "ABC",
- "active": true,
- "pinned": true,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "budget_progress": 30.5,
- "default_rate_dollars": "150.00",
- "billable": true
}Delete a Project. This will not delete associated time Entries.
| projectId required | integer |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123",
- "status": "deleted"
}Returns all Tasks in the current account
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
[- {
- "id": "123456",
- "name": "Development",
- "pinned": true,
- "default_rate_dollars": "150.00",
- "entries_count": 342
}
]Create a new Task for time tracking
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
| name required | string non-empty Task name |
| pinned | boolean Default: false Whether the task is pinned for quick access |
| default_rate_dollars | string (CurrencyString) ^\d+\.\d{2}$ Default hourly rate for this Task type |
{- "id": "123456",
- "name": "Development",
- "pinned": true,
- "default_rate_dollars": "150.00"
}{- "id": "123456",
- "name": "Development",
- "pinned": true,
- "default_rate_dollars": "150.00",
- "entries_count": 342
}Retrieve details of a specific Task
| taskId required | integer |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123456",
- "name": "Development",
- "pinned": true,
- "default_rate_dollars": "150.00",
- "entries_count": 342
}Update Task details
| taskId required | integer |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
| name required | string non-empty Task name |
| pinned | boolean Default: false Whether the task is pinned for quick access |
| default_rate_dollars | string (CurrencyString) ^\d+\.\d{2}$ Default hourly rate for this Task type |
{- "id": "123456",
- "name": "Development",
- "pinned": true,
- "default_rate_dollars": "150.00"
}{- "id": "123456",
- "name": "Development",
- "pinned": true,
- "default_rate_dollars": "150.00",
- "entries_count": 342
}Delete a Task. This will also remove the Task from any existing Entries in the system.
| taskId required | integer |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": "123",
- "status": "deleted"
}Returns the current account's billable items for use with expense updates.
The default_rate_cents value is applied automatically when an expense is updated with item_id.
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
[- {
- "id": "123",
- "name": "Consulting",
- "description": "Hourly consulting work",
- "default_rate_cents": 15000
}
]Expense tracking and management.
Note: The Expenses feature must be enabled on your account before these endpoints can be used. Contact support to enable this feature. Requests to these endpoints will return a 422 Unprocessable Entity error if the feature is not enabled.
Returns expenses in the current account. Non-admin users only see their own expenses. Supports filtering by contact, project, user account, date ranges, and invoice status.
| contact_id | integer Filter by contact ID |
| project_id | integer Filter by project ID |
| user_account_id | integer Filter by user account ID (admin only) |
| from | string <date> Filter expenses from this date (YYYY-MM-DD) |
| to | string <date> Filter expenses to this date (YYYY-MM-DD) |
| since | string <date-time> Filter expenses updated since this timestamp (ISO 8601) |
| invoiced_only | boolean Only return invoiced expenses |
| uninvoiced_only | boolean Only return uninvoiced expenses |
| limit | integer [ 1 .. 1000 ] Default: 500 Maximum number of expenses to return (1-1000, default 500) |
| offset | integer >= 0 Default: 0 Number of expenses to skip (for pagination) |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
[- {
- "id": "1234",
- "description": "Office supplies",
- "quantity": 2,
- "unit_amount": "25.50",
- "amount": "51.00",
- "currency": "USD",
- "date": "2024-01-15",
- "contact_id": "789",
- "project_id": "1011",
- "user_account_id": "456",
- "invoice_id": null,
- "manually_invoiced": false,
- "written_off": false,
- "item": {
- "id": "123",
- "name": "Office Supplies"
}, - "created_at": "2024-01-15T10:30:00Z",
- "updated_at": "2024-01-15T10:30:00Z"
}
]Update an existing expense. You can only update your own expenses unless you have reports admin permissions.
Expense update semantics:
item_id uses the item's default_rate_cents and allows a variable quantityrate_cents without item_id creates a one-off expense with an implicit quantity of 1manually_invoiced to true marks the expense as invoiced without linking it to an invoice object| expenseId required | integer Example: 1234 Expense ID |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
object |
{- "expense": {
- "item_id": 123,
- "quantity": 2,
- "manually_invoiced": true
}
}{- "id": "1234",
- "description": "Office supplies",
- "quantity": 2,
- "unit_amount": "25.50",
- "amount": "51.00",
- "currency": "USD",
- "date": "2024-01-15",
- "contact_id": "789",
- "project_id": "1011",
- "user_account_id": "456",
- "invoice_id": null,
- "manually_invoiced": false,
- "written_off": false,
- "item": {
- "id": "123",
- "name": "Office Supplies"
}, - "created_at": "2024-01-15T10:30:00Z",
- "updated_at": "2024-01-15T10:30:00Z"
}Retrieve a saved report configuration and optionally execute it to get current data. Reports are pre-configured filters and groupings for time entry data.
| reportId required | integer Report ID |
| run | boolean Default: false Execute the report and return data (not just configuration) |
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
{- "id": 1,
- "name": "Weekly Time Summary",
- "filters": {
- "from": "2024-01-15",
- "to": "2024-01-21",
- "contacts": [
- "789"
]
}, - "grouping": "user",
- "data": {
- "total_duration": 144000,
- "total_duration_hours": "40.0",
- "groups": [
- {
- "user_id": "123",
- "duration": 144000,
- "duration_hours": "40.0"
}
]
}
}Generate a report with custom filters without saving the configuration. This is useful for one-time reports or exploring data before saving a report.
| X-Account-ID | string (Recommended) Account ID to use for the API requests. If not specified, the user's active account will be used.
We recommend specifying this parameter to ensure consistency if the user is a member of multiple MinuteDock accounts.
You can determine the currently active account by making a request to the |
object |
{- "report": {
- "from": "2024-01-01",
- "to": "2024-01-31",
- "contacts": [
- 789
], - "grouping": "project",
- "include_entries": true
}
}{- "total_duration": 0,
- "total_duration_hours": "string",
- "groups": [
- { }
], - "entries": [
- {
- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}
]
}| user_account_id | string (ID) The correct ID to use for this user within the account. Use this value when associating users with entries or other resources. |
| active | boolean Whether the user is active |
string <email> | |
| first_name | string |
| last_name | string |
| billing_rate | string (CurrencyString) ^\d+\.\d{2}$ Default billing rate for the user |
| id | string Deprecated Legacy user ID - do not use for new integrations.
This field exists only for backward compatibility with old API clients.
Always use |
| account_id | string Deprecated ID of the associated Account. Redundant as this is always the active API account. (Will be removed in the next major version.) |
| time_zone_id | string Deprecated |
| time_zone_offset | string Deprecated |
| push_channel_token | string Deprecated |
{- "user_account_id": "123456",
- "active": true,
- "email": "john.doe@example.com",
- "first_name": "John",
- "last_name": "Doe",
- "billing_rate": "150.00",
- "id": "123456",
- "account_id": "123456",
- "time_zone_id": "string",
- "time_zone_offset": "string",
- "push_channel_token": "string"
}| id | string (ID) The unique identifier for the entity. |
| name | string |
{- "id": "123456",
- "name": "Acme Corporation"
}| id | string (ID) The unique identifier for the entity. |
| name required | string non-empty |
| short_code | string Short code identifier for the Contact. In the application UI, time can be tracked for a Contact using this @identifier |
| active | boolean Default: true Whether the contact is active |
| pinned | boolean Default: false Whether the contact is pinned for quick access |
| budget_type | string or null Default: "null" Enum: "hours" "billable" The type of budget tracking. If not set (null), the budget will not be tracked. An 'hours' budget will track the number of hours for time entries within the budget period. A 'billable' budget will track the billable value of time entries within the budget period. |
| budget_frequency | string or null Default: "null" Enum: "total" "weekly" "monthly" "quarterly" "yearly" The time period which the budget will report on |
| budget_target | number or null Default: "null" The targetted value for the budget. For an hourly budget, this is the number of hours. For a money budget, this is the amount in dollars. |
| budget_progress | number or null Default: "null" The current value for the budget. This is the sum of all time entries for the current budget period. |
CurrencyString (string) or null Default hourly rate for tracked time. If not set (null), the appropriate next rate will be used. A time entry's billing rate will be chosen, in order, from:
| |
| billable | boolean Default: true Whether tracked time should be billed (Rate is not 0) |
{- "id": "123456",
- "name": "ABC Industries",
- "short_code": "ABC",
- "active": true,
- "pinned": false,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "budget_progress": 30.5,
- "default_rate_dollars": "150.00",
- "billable": true
}| id | string (ID) The unique identifier for the entity. |
| name required | string non-empty |
| contact_id required | string (ID) ID of the Contact this project belongs to. A Project is always associated with a Contact. |
| short_code | string Short code identifier for the Project. In the application UI, time can be tracked for a Project using this #code |
| active | boolean Default: true Whether the project is active |
| pinned | boolean Default: false Whether the project is pinned for quick access |
| budget_type | string or null Default: "null" Enum: "hours" "billable" The type of budget tracking. If not set (null), the budget will not be tracked. An 'hours' budget will track the number of hours for time entries within the budget period. A 'billable' budget will track the billable value of time entries within the budget period. |
| budget_frequency | string or null Default: "null" Enum: "total" "weekly" "monthly" "quarterly" "yearly" The time period which the budget will report on |
| budget_target | number or null Default: "null" The targetted value for the budget. For an hourly budget, this is the number of hours. For a money budget, this is the amount in dollars. |
| budget_progress | number or null Default: "null" The current value for the budget. This is the sum of all time entries for the current budget period. |
CurrencyString (string) or null Default hourly rate for tracked time. If not set (null), the appropriate next rate will be used. A time entry's billing rate will be chosen, in order, from:
| |
| billable | boolean Default: true Whether tracked time should be billed (Rate is not 0) |
{- "id": "123456",
- "name": "Website Redesign",
- "contact_id": "123456",
- "short_code": "ABC",
- "active": true,
- "pinned": true,
- "budget_type": "hours",
- "budget_frequency": "monthly",
- "budget_target": 40.5,
- "budget_progress": 30.5,
- "default_rate_dollars": "150.00",
- "billable": true
}| id | string (ID) Unique identifier for the Task |
| name required | string non-empty Task name |
| pinned | boolean Default: false Whether the task is pinned for quick access |
| default_rate_dollars | string (CurrencyString) ^\d+\.\d{2}$ Default hourly rate for this Task type |
| entries_count | integer Number of entries using this task |
{- "id": "123456",
- "name": "Development",
- "pinned": true,
- "default_rate_dollars": "150.00",
- "entries_count": 342
}| id | string (ID) Unique identifier for the Item |
| name required | string non-empty Item name |
| description | string Optional item description |
| default_rate_cents | integer Default billable rate in cents used when the item is attached to an expense |
{- "id": "123456",
- "name": "Consulting",
- "description": "Hourly consulting work",
- "default_rate_cents": 15000
}| id | string The unique identifier for the entity. |
| user_account_id required | string The ID of the User who has logged this entry. (See User.user_account_id) |
ID (string) or null Default: null Associated Contact ID | |
ID (string) or null Default: null Associated Project ID | |
| task_ids | Array of strings (ID) Array of associated Task IDs |
| description | string Description of work performed |
| duration | integer >= 0 The time entry's duration (in seconds) |
| duration_hours | string The time entry's duration (in hours) |
| account_id | string Deprecated Account this entry belongs to (deprecated) |
| user_id | string Deprecated Legacy user ID - do not use for new integrations.
This field exists only for backward compatibility with old API clients.
Always use |
string or null Date of the entry (YYYY-MM-DD). Defaults to today's date if not provided. Null for active timers. | |
| invoice_id | string The Invoice that this entry was billed in, if any. (An entry is considered 'billed' if it has been included in an invoice.) |
| billing_rate | string (CurrencyString) ^\d+\.\d{2}$ The time entry's billing rate |
| updated_at | string <date-time> Last update timestamp |
string or null Deprecated The date the time entry is logged on, in the user's timezone, as a timestamp (deprecated). Null for unlogged entries. | |
| logged | boolean Deprecated Whether the entry is logged (completed) (deprecated) |
| rate | string (CurrencyString) ^\d+\.\d{2}$ Deprecated Use billing_rate instead |
{- "id": "123456",
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "date": "2024-01-20",
- "invoice_id": "123456",
- "billing_rate": "150.00",
- "updated_at": "2024-01-20T15:45:00Z",
- "logged_at": "2024-01-20T14:30:00-05:00",
- "logged": true,
- "rate": "150.00"
}| id | string Unique identifier for the expense |
| description required | string Description of the expense |
| quantity required | number Quantity of items or units |
| unit_amount | string Unit price in decimal format |
| amount | string Total amount (quantity × unit price) in decimal format |
| currency | string Currency code |
| date required | string <date> Date of the expense (YYYY-MM-DD) |
| contact_id | string or null Associated contact/client ID |
| project_id | string or null Associated project ID |
| user_account_id required | string The ID of the user who created this expense |
| invoice_id | string or null Associated invoice ID if expense has been invoiced |
| manually_invoiced | boolean Whether the expense has been marked as invoiced without linking it to an invoice |
| written_off | boolean Whether the expense has been written off |
object or null Associated item/rate information | |
| created_at | string <date-time> Creation timestamp |
| updated_at | string <date-time> Last update timestamp |
{- "id": "1234",
- "description": "Office supplies",
- "quantity": 2,
- "unit_amount": "25.50",
- "amount": "51.00",
- "currency": "USD",
- "date": "2024-01-15",
- "contact_id": "789",
- "project_id": "1011",
- "user_account_id": "456",
- "invoice_id": null,
- "manually_invoiced": false,
- "written_off": false,
- "item": {
- "id": "123",
- "name": "Office Supplies"
}, - "created_at": "2024-01-15T10:30:00Z",
- "updated_at": "2024-01-15T10:30:00Z"
}| id | string Deprecated The unique identifier for the entity. |
| user_account_id | string The ID of the User who has logged this entry. (See User.user_account_id) |
ID (string) or null Default: null Associated Contact ID | |
ID (string) or null Default: null Associated Project ID | |
| task_ids | Array of strings (ID) Array of associated Task IDs |
| description | string Description of work performed |
| duration | integer >= 0 The time entry's duration (in seconds) |
| duration_hours | string The time entry's duration (in hours) |
| account_id | string Deprecated Account this entry belongs to (deprecated) |
| user_id | string Deprecated Legacy user ID - do not use for new integrations.
This field exists only for backward compatibility with old API clients.
Always use |
| invoice_id | any Deprecated |
| rate | any Deprecated |
| timer_active | boolean Whether the timer is currently running |
| logged | boolean If true, the Entry will be logged. |
| version_id | string Unique version identifier for conflict resolution |
| version_client_id | string Client identifier that made the last update |
| version_number | integer Incremental version number |
{- "id": null,
- "user_account_id": "123456",
- "contact_id": null,
- "project_id": null,
- "task_ids": [
- "123456"
], - "description": "Working on API documentation",
- "duration": 3600,
- "duration_hours": "1.0",
- "account_id": "123456",
- "user_id": "123456",
- "invoice_id": null,
- "rate": null,
- "timer_active": true,
- "logged": false,
- "version_id": "550e8400-e29b-41d4-a716-446655440000",
- "version_client_id": "web-app",
- "version_number": 42
}Currency amount formatted as a string with exactly 2 decimal places
"150.00"