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. OAuth 2.0 access tokens are the recommended
and primary way to authenticate with the MinuteDock API for new integrations. Legacy personal API
keys (X-API-Key) are still accepted for backward compatibility but are deprecated — see
Legacy API Keys below.
MinuteDock authenticates API requests with OAuth 2.0 access tokens, sent as a standard
Authorization: Bearer <token> header. There are two ways to obtain an access token,
depending on what you're building:
Whichever path you use, the resulting tokens work identically. To obtain OAuth client credentials (client ID and secret), contact us at team@minutedock.com.
If you just want to authenticate as yourself (for a script, internal tool, CI job, or other
first-party integration) you don't need to run the full OAuth flow or register an OAuth
application. You can create a Personal Access Token from within MinuteDock — this is a
ready-to-use OAuth access token, issued under your own user, that you send as a standard
Authorization: Bearer <token> header.
Personal access tokens behave exactly like OAuth access tokens obtained through the authorization-code flow:
X-Account-ID header is ignored. Create a separate token for each account you need to access.read and write scopes.To create one:
curl -H "Authorization: Bearer <your-personal-access-token>" \
https://minutedock.com/api/v1/users/me
Treat personal access tokens like a password: keep them private, never commit them to source control, and revoke any token you no longer need from the same Manage Access Tokens page.
Register an OAuth client (client ID and secret) with us, then run the authorization-code flow so each of your users authorizes your integration and selects the MinuteDock account to use:
1. Redirect user to /oauth/authorize
2. User logs in and selects which account to authorize
3. MinuteDock redirects back with an authorization code
4. Exchange code for access token at /oauth/token
5. Include token in requests: Authorization: Bearer <token>
curl -H "Authorization: Bearer <access-token>" \
https://minutedock.com/api/v1/users/me
All OAuth access tokens — whether obtained as a personal access token or via the authorization
flow — are account-scoped. Each token is bound to the specific account the user selected, and
the X-Account-ID header is ignored for OAuth requests. For multi-account access, obtain a
separate token per account.
⚠️ Deprecated. Personal API keys (
X-API-Key) are legacy credentials retained only for backward compatibility with existing integrations. Do not use API keys for new integrations — use OAuth 2.0 instead. API keys may be removed in a future major API version.
Each request must include the legacy 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 an API key (existing integrations only):
Legacy API keys are user-scoped and can access any account the user belongs to. 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 when using legacy API keys, to ensure consistency, especially if you belong to multiple accounts. This header is ignored for OAuth requests, where the account is fixed by the token itself.
To determine which accounts you have access to:
GET /accountsGET /accounts/currentOAuth access token (recommended):
curl -H "Authorization: Bearer abc123def456" \
https://minutedock.com/api/v1/users/me
Legacy API key (deprecated) — basic request:
curl -H "X-API-Key: abc123def456" \
https://minutedock.com/api/v1/users/me
Legacy API key (deprecated) — 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 an OAuth access token:
curl -X POST \
-H "Authorization: Bearer abc123def456" \
-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
| 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": "123",
- "email": "john.doe@example.com",
- "first_name": "John",
- "last_name": "Doe",
- "billing_rate": "100.00",
- "archived": false
}, - {
- "id": "124",
- "email": "jane.smith@example.com",
- "first_name": "Jane",
- "last_name": "Smith",
- "billing_rate": "120.00",
- "archived": true
}
]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"
}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"
}Returns invoices in the current account. Requires the Manage Invoices permission. Results are sorted by invoice date descending.
| contact_id | integer Filter by contact ID |
| from | string <date> Filter invoices from this invoice date |
| to | string <date> Filter invoices to this invoice date |
| since | string <date-time> Filter invoices updated since this timestamp |
| sent_only | boolean Only return sent invoices |
| draft_only | boolean Only return draft invoices |
| archived | boolean Default: false Return archived invoices instead of active invoices |
| 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 |
| 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",
- "contact_id": 789,
- "number": "INV-000123",
- "reference": "January services",
- "status": "sent",
- "archived": false,
- "date": "2024-01-31",
- "due_date": "2024-02-14",
- "currency": "USD",
- "subtotal": "250.00",
- "tax": "0.00",
- "total": "250.00",
- "delivery": {
- "service": "xero",
- "id": "xero_invoice_id"
}
}
]Retrieve an invoice by ID, including its line items. Requires the Manage Invoices permission.
| invoiceId required | integer Example: 1234 Invoice 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",
- "contact_id": 0,
- "number": "string",
- "reference": "string",
- "status": "draft",
- "sent_at": "2019-08-24T14:15:22Z",
- "archived": true,
- "date": "2019-08-24",
- "due_date": "2019-08-24",
- "currency": "string",
- "subtotal": "string",
- "tax": "string",
- "total": "string",
- "delivery": {
- "service": "xero",
- "id": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "line_items": [
- {
- "id": "123456",
- "description": "string",
- "quantity": "string",
- "unit_amount": "string",
- "subtotal": "string",
- "tax": "string",
- "total": "string",
- "position": 0
}
]
}DEPRECATED: Use POST /reports/generate instead.
Retrieve a saved report configuration and optionally execute it to get current data. Reports are pre-configured filters and groupings for time entry data. For new integrations, use the /reports/generate endpoint to run ad-hoc reports with custom filters.
| 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 summary with custom filters without saving the configuration. Returns aggregated totals for matching time entries. Billing-related fields are only included for users with appropriate permissions.
| 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 |
| from | string <date> Start date (inclusive) |
| to | string <date> End date (inclusive) |
| users | Array of integers Deprecated DEPRECATED: Use |
(Array of strings or integers or null) (ListFilter) | |
(Array of strings or integers or null) (ListFilter) | |
(Array of strings or integers or null) (ListFilter) | |
(Array of strings or integers or null) (ListFilter) | |
| billable_only | boolean Only include billable entries |
| unbillable_only | boolean Only include unbillable entries |
| invoiced_only | boolean Only include invoiced entries |
| uninvoiced_only | boolean Only include uninvoiced entries |
| group_by | Array of strings Items Enum: "contact" "user" "project" "date" "month" "year" Dimensions to group results by. When provided, the response
includes a Date dimensions ( |
{- "from": "2024-01-01",
- "to": "2024-01-31",
- "contacts": [
- 789
], - "billable_only": true,
- "group_by": [
- "contact"
]
}{- "description": "Report for Jan 2024",
- "entries": 42,
- "hours": "156.5",
- "billable_hours": "120.25",
- "billable_amount": {
- "USD": "12025.00",
- "NZD": "3500.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. |
| archived | boolean Whether the user is archived |
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",
- "archived": false,
- "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 (ID) The unique identifier for the entity. |
| description | string |
| quantity | string Display quantity for the line item |
| unit_amount | string Unit price in decimal format |
| subtotal | string Line subtotal in decimal format |
| tax | string Tax amount in decimal format |
| total | string Line total including tax in decimal format |
| position | integer |
{- "id": "123456",
- "description": "string",
- "quantity": "string",
- "unit_amount": "string",
- "subtotal": "string",
- "tax": "string",
- "total": "string",
- "position": 0
}| service | string Enum: "xero" "quickbooks" "freshbooks" "wave" "myob" |
| id | string Remote invoice ID in the accounting service |
{- "service": "xero",
- "id": "string"
}| id | string (ID) The unique identifier for the entity. |
| contact_id | integer Associated contact/client ID |
| number | string or null |
| reference | string or null |
| status | string Enum: "draft" "sent" |
| sent_at | string or null <date-time> |
| archived | boolean |
| date | string <date> |
| due_date | string <date> |
| currency | string |
| subtotal | string Invoice subtotal in decimal format |
| tax | string Invoice tax total in decimal format |
| total | string Invoice total in decimal format |
InvoiceDelivery (object) or null Remote delivery details when the invoice has been sent to an accounting service | |
| created_at | string <date-time> |
| updated_at | string <date-time> |
{- "id": "123456",
- "contact_id": 0,
- "number": "string",
- "reference": "string",
- "status": "draft",
- "sent_at": "2019-08-24T14:15:22Z",
- "archived": true,
- "date": "2019-08-24",
- "due_date": "2019-08-24",
- "currency": "string",
- "subtotal": "string",
- "tax": "string",
- "total": "string",
- "delivery": {
- "service": "xero",
- "id": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| 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"