Integrations
Elastic Time integrates with external tools for issue tracking, time logging, and data import/export.
Jira Integration
Warning: Always check scripts before you run them. If you are unsure about this feature, we recommend that you don’t use it.
Jira Worklogs Script
Export your time entries as Jira worklogs using a browser script:
- Go to Reports
- Filter to the desired date range and project
- Click “Jira Worklogs” to copy the script
- Open your Jira instance in a browser
- Open Developer Tools (F12)
- Go to the Console tab
- Paste and run the script
How It Works
- The script uses your existing Jira session for authentication
- No API tokens or credentials needed
- Activities are matched to Jira issues by tag (the tag should be the issue key)
- Time is logged to each issue
Requirements
- You must be logged into Jira in the same browser
- Tags must match Jira issue keys (e.g.,
PROJ-123) - Your Jira user must have permission to log work
Aggregation
The script aggregates time by issue and day:
- Multiple activities for
PROJ-123on the same day become one worklog - The total time is summed
- Descriptions are combined
Jira Comments Script
Import activity notes as Jira comments:
- Go to Reports
- Filter your activities
- Click “Jira Comments” to copy the script
- Run in your browser console while on Jira
Differences from Worklogs
- Only includes activities with notes
- One comment per activity (not aggregated)
- Comments include the activity description and note
- Useful for documenting work performed
Tempo CSV Export
For Jira Server/Data Center with Tempo Timesheets:
- Go to Reports
- Filter your activities
- Click “Tempo CSV” to download
- Import the CSV into Tempo
CSV Format
The export creates a Tempo-compatible format:
- Issue key (from tags)
- Date
- Hours (aggregated by issue and day)
- Description
Ticket System Linking
Link activity tags to any URL-based issue tracker.
Configuration
- Go to your client’s detail page
- Set the Ticket URL Prefix
- Save
Supported Systems
Any system with URL-based issue viewing:
| System | Example Prefix |
|---|---|
| Jira Cloud | https://yourcompany.atlassian.net/browse/ |
| Jira Server | https://jira.company.com/browse/ |
| GitHub Issues | https://github.com/org/repo/issues/ |
| GitLab Issues | https://gitlab.com/org/repo/-/issues/ |
| Linear | https://linear.app/team/issue/ |
| Asana | https://app.asana.com/0/project/ |
Usage
When you export to HTML format:
- Tags become clickable links
- Clicking a tag opens the issue in a new tab
- Makes it easy to reference original tickets
Example: Tag PROJ-123 with prefix https://jira.company.com/browse/ links to https://jira.company.com/browse/PROJ-123
JSON Account Export
The Export everything (JSON) button in Preferences downloads a complete copy of an account as one JSON file. It is the format Alba Ticket imports when an account moves there, and it is documented here so that any other application can read it too. Every entity carries the identifiers it has in Elastic Time, so a reader can relate rows to each other and recognise the same row again in a later export.
Getting the file
- Go to Preferences
- Find the Export Activities section
- Click “Export everything (JSON)”
The download is served as application/json and named elastictime-<email>-<date>.json, for example elastictime-jane@example.com-2026-09-30.json. Only the signed-in user’s own account is exported; a session is required.
Conventions
| Rule | Detail |
|---|---|
| Encoding | UTF-8 JSON, one object at the top level |
| Keys | snake_case |
| Identifiers | Strings; the ids Elastic Time uses internally. They are stable across exports of the same account |
| Times | ISO 8601 in UTC with millisecond precision, for example 2026-09-01T07:00:00.000Z |
| Dates | YYYY-MM-DD (phase start and end dates have no time component) |
| Decimals | Strings with two decimal places, for example "100.00", so no precision is lost |
| Absent values | null, never a missing key. Every key listed below is always present |
| Soft deletes | Rows deleted in Elastic Time are still exported, with deleted_at set to the time of deletion. Live rows have deleted_at: null. Readers that only want current data must filter on it |
| Row timestamps | Every row except user has created_at, updated_at and deleted_at |
| Ordering | Clients, contracts, projects, tag categories, team members and colleagues are ordered by created_at; phases by start_date; activities by start_time |
Top-level structure
{
"format": "elastic-time-export",
"version": 1,
"exported_at": "2026-09-30T12:00:00.000Z",
"user": { ... },
"colleagues": [ ... ],
"clients": [ ... ],
"phases": [ ... ],
"activities": [ ... ],
"counts": { ... }
} | Key | Type | Meaning |
|---|---|---|
format | string | Always "elastic-time-export". Check it before reading anything else |
version | number | Format version, currently 1. A breaking change to the shape raises it |
exported_at | time | When the export was produced |
user | object | The account owner and their invoice settings |
colleagues | array | Colleague links and pending invitations involving the owner |
clients | array | The owner’s clients, each with its team members, contracts, tag categories and projects nested inside |
phases | array | The owner’s billing periods |
activities | array | Every time entry the owner owns, plus team members’ entries on the owner’s clients’ projects |
counts | object | Number of rows of each entity in the file, deleted rows included |
user
The account owner. This is the only object without updated_at and deleted_at.
| Key | Type | Meaning |
|---|---|---|
id | string | The owner’s user id, referenced by user_id fields elsewhere |
name | string | Display name |
email | string | Login email |
company_name | string or null | Invoice settings: company name |
company_address | string or null | Invoice settings: address, may contain newlines |
company_phone | string or null | Invoice settings: phone |
company_email | string or null | Invoice settings: contact email shown on invoices |
invoice_footer | string or null | Footer text printed on invoices |
tax_label | string or null | Name of the tax applied to invoices, such as "VAT" |
tax_rate | decimal or null | Tax percentage, for example "20.00" |
billing_currency | string | Default currency code for new contracts, for example "USD" |
created_at | time | When the account was created |
colleagues[]
A colleague row links two users, or records an invitation that has not been accepted yet. Rows where the owner is either side are exported.
| Key | Type | Meaning |
|---|---|---|
id | string | Row id |
user_id_a | string | The inviting user’s id |
user_a_email | string or null | The inviting user’s email |
user_id_b | string or null | The invited user’s id once they accepted, otherwise null |
user_b_email | string or null | The invited user’s email once they accepted, otherwise null |
invite_email | string or null | The address the invitation was sent to while it is pending |
status | "accepted" or "pending" | "accepted" when user_id_b is set |
created_at, updated_at, deleted_at | time or null | Row timestamps |
clients[]
| Key | Type | Meaning |
|---|---|---|
id | string | Client id, referenced by nothing directly; projects and contracts are nested inside |
name | string | Client name |
billing_email | string or null | Where invoices are addressed |
billing_address | string or null | Billing address, may contain newlines |
ticket_url_prefix | string or null | URL prefix that turns a tag into a ticket link, see Ticket System Linking |
has_tag_categories | boolean | Whether tags are grouped into categories for this client’s invoices |
default_invoice_label | string or null | Invoice label for activities whose tags match no category |
team_members | array | See below |
contracts | array | See below |
tag_categories | array | See below |
projects | array | See below |
created_at, updated_at, deleted_at | time or null | Row timestamps |
clients[].team_members[]
Users other than the owner who may log time on this client’s projects.
| Key | Type | Meaning |
|---|---|---|
id | string | Row id |
user_id | string or null | The team member’s user id, null if the row has no user |
email | string or null | The team member’s email, null if the row has no user |
created_at, updated_at, deleted_at | time or null | Row timestamps |
clients[].contracts[]
| Key | Type | Meaning |
|---|---|---|
id | string | Contract id, referenced by phases[].contract_id |
name | string | Contract name |
reference | string or null | Reference or purchase order number |
invoice_description | string or null | Description used for the contract’s invoice line items |
billing_rate | decimal or null | Hourly rate |
currency | string or null | Currency code of the rate, for example "EUR" |
created_at, updated_at, deleted_at | time or null | Row timestamps |
clients[].tag_categories[]
| Key | Type | Meaning |
|---|---|---|
id | string | Row id |
name | string | Category name |
invoice_label | string | Label shown for the category on invoices |
tags | array of strings | The tags that belong to the category, in the case they were typed. Matching is case-insensitive |
created_at, updated_at, deleted_at | time or null | Row timestamps |
clients[].projects[]
| Key | Type | Meaning |
|---|---|---|
id | string | Project id, referenced by activities[].project_id and phases[].project_id |
name | string | Project name |
created_at, updated_at, deleted_at | time or null | Row timestamps |
phases[]
| Key | Type | Meaning |
|---|---|---|
id | string | Phase id |
name | string | Phase name |
user_id | string | Always the owner’s id |
contract_id | string or null | The contract the phase bills against, null for a standalone phase |
project_id | string or null | Limits the phase to one project of the contract’s client |
start_date | date | First day, inclusive |
end_date | date | Last day, inclusive |
billing_rate | decimal or null | Overrides the contract’s rate when set |
max_days_available | number or null | Working days available in the phase |
hours_per_day | decimal | Hours that make up one working day, default "8.00" |
created_at, updated_at, deleted_at | time or null | Row timestamps |
activities[]
Time entries. The owner’s own entries are all included, whatever project they belong to. Entries logged by other users are included when they belong to a project of one of the owner’s clients, so the export holds everything the owner can see in reports.
| Key | Type | Meaning |
|---|---|---|
id | string | Activity id |
user_id | string | Who logged the time |
user_email | string | That user’s email, so a reader can match people without the ids |
start_time | time | Start |
end_time | time or null | End, null while the activity is still running |
description | string | What was done |
note | string or null | Personal note |
tags | array of strings | Tags in the case they were typed; an empty array when there are none |
project_id | string or null | The project, found under clients[].projects[], or null |
locked_at | time or null | When the entry was locked against editing, null if unlocked |
locked_by_user_id | string or null | Who locked it |
locked_by_email | string or null | That user’s email |
created_at, updated_at, deleted_at | time or null | Row timestamps |
counts
The number of rows of each entity in the file, deleted rows included, so an importer can check it read the whole file. projects, contracts, tag_categories and team_members are totals across all clients.
{
"clients": 2,
"projects": 3,
"contracts": 2,
"tag_categories": 1,
"team_members": 2,
"phases": 2,
"activities": 5,
"colleagues": 1
} Example
A small account with one client, one team member and two activities:
{
"format": "elastic-time-export",
"version": 1,
"exported_at": "2026-09-30T12:00:00.000Z",
"user": {
"id": "u_jane",
"name": "Jane Doe",
"email": "jane@example.com",
"company_name": "Doe Consulting",
"company_address": "1 High Street\nLondon",
"company_phone": null,
"company_email": "billing@example.com",
"invoice_footer": "Payment within 30 days",
"tax_label": "VAT",
"tax_rate": "20.00",
"billing_currency": "GBP",
"created_at": "2024-01-01T00:00:00.000Z"
},
"colleagues": [
{
"id": "col_1",
"user_id_a": "u_jane",
"user_a_email": "jane@example.com",
"user_id_b": "u_sam",
"user_b_email": "sam@example.com",
"invite_email": null,
"status": "accepted",
"created_at": "2024-02-01T00:00:00.000Z",
"updated_at": "2024-02-02T00:00:00.000Z",
"deleted_at": null
}
],
"clients": [
{
"id": "c_acme",
"name": "ACME",
"billing_email": "ap@acme.example",
"billing_address": "1 Main Street",
"ticket_url_prefix": "https://acme.example/browse/",
"has_tag_categories": true,
"default_invoice_label": "Other",
"created_at": "2024-01-10T00:00:00.000Z",
"updated_at": "2024-01-10T00:00:00.000Z",
"deleted_at": null,
"team_members": [
{
"id": "tm_sam",
"user_id": "u_sam",
"email": "sam@example.com",
"created_at": "2024-02-02T00:00:00.000Z",
"updated_at": "2024-02-02T00:00:00.000Z",
"deleted_at": null
}
],
"contracts": [
{
"id": "k_retainer",
"name": "Retainer",
"reference": "PO-4711",
"invoice_description": "Consulting",
"billing_rate": "100.00",
"currency": "GBP",
"created_at": "2024-01-10T00:00:00.000Z",
"updated_at": "2024-01-10T00:00:00.000Z",
"deleted_at": null
}
],
"tag_categories": [
{
"id": "tc_dev",
"name": "Development",
"invoice_label": "Dev",
"tags": ["dev", "Review"],
"created_at": "2024-01-10T00:00:00.000Z",
"updated_at": "2024-01-10T00:00:00.000Z",
"deleted_at": null
}
],
"projects": [
{
"id": "p_web",
"name": "Website",
"created_at": "2024-01-10T00:00:00.000Z",
"updated_at": "2024-01-10T00:00:00.000Z",
"deleted_at": null
}
]
}
],
"phases": [
{
"id": "ph_sep",
"name": "September",
"user_id": "u_jane",
"contract_id": "k_retainer",
"project_id": "p_web",
"start_date": "2026-09-01",
"end_date": "2026-09-30",
"billing_rate": null,
"max_days_available": 10,
"hours_per_day": "8.00",
"created_at": "2026-08-20T00:00:00.000Z",
"updated_at": "2026-08-20T00:00:00.000Z",
"deleted_at": null
}
],
"activities": [
{
"id": "a_1",
"user_id": "u_jane",
"user_email": "jane@example.com",
"start_time": "2026-09-01T07:00:00.000Z",
"end_time": "2026-09-01T09:30:00.000Z",
"description": "Fix the checkout bug",
"note": "Found it in the flex gap",
"tags": ["Dev", "WEB-1"],
"project_id": "p_web",
"locked_at": "2026-09-05T10:00:00.000Z",
"locked_by_user_id": "u_jane",
"locked_by_email": "jane@example.com",
"created_at": "2026-09-01T09:31:00.000Z",
"updated_at": "2026-09-05T10:00:00.000Z",
"deleted_at": null
},
{
"id": "a_2",
"user_id": "u_sam",
"user_email": "sam@example.com",
"start_time": "2026-09-02T08:00:00.000Z",
"end_time": "2026-09-02T09:00:00.000Z",
"description": "Review the fix",
"note": null,
"tags": ["review"],
"project_id": "p_web",
"locked_at": null,
"locked_by_user_id": null,
"locked_by_email": null,
"created_at": "2026-09-02T09:01:00.000Z",
"updated_at": "2026-09-02T09:01:00.000Z",
"deleted_at": null
}
],
"counts": {
"clients": 1,
"projects": 1,
"contracts": 1,
"tag_categories": 1,
"team_members": 1,
"phases": 1,
"activities": 2,
"colleagues": 1
}
} Reading the file
- Check
formatandversionfirst, and refuse a file whose values differ from those you support - Decide whether deleted rows matter to you; if not, drop every row whose
deleted_atis set, and drop nested rows of a deleted client too - Resolve
project_idagainstclients[].projects[]andcontract_idagainstclients[].contracts[]; a project of a deleted client may still be referenced by live activities - Match people by email rather than id if you are merging with data from elsewhere;
user_emailandlocked_by_emailare provided for this - Compare what you read with
countsto make sure nothing was skipped
CSV Import/Export
Exporting Data
Export your activities for backup or analysis:
- Go to Preferences
- Find the Export section
- Select the year to export
- Click “Download CSV”
The export includes:
- All activity fields
- Full descriptions and notes
- Tags (comma-separated)
- Project and client information
Importing Data
Import activities from a CSV file:
- Go to Preferences
- Find the Import section
- Select your CSV file
- Configure import options
- Click “Import”
Import Options
- Timezone - How to interpret times without timezone info (defaults to your current timezone)
CSV Format
The import accepts flexible date/time formats:
- ISO 8601:
2024-01-15T09:00:00 - Date and time columns:
2024-01-15+09:00 - Various date formats:
01/15/2024,15-01-2024
Required Columns
Email- User email addressDescription- Activity descriptionStart- Start datetime, or use separateStart dateandStart timecolumns
Optional Columns
End- End datetime, or use separateEnd dateandEnd timecolumnsClient- Client nameProject- Project nameTags- Comma-separated tagsNote- Personal note
Example CSV
Email,Start date,Start time,End date,End time,Description,Client,Project,Tags,Note
alice@example.com,2025-01-15,09:00,2025-01-15,10:30,Sprint planning,Acme Corp,Website Redesign,PROJ-101,
alice@example.com,2025-01-15,10:45,2025-01-15,12:30,Implement login form,Acme Corp,Website Redesign,"PROJ-102,frontend",Added validation
bob@example.com,2025-01-15,13:30,2025-01-15,17:00,API development,Acme Corp,Website Redesign,PROJ-103,REST endpoints
alice@example.com,2025-01-16,09:00,2025-01-16,11:00,Code review,Acme Corp,Website Redesign,PROJ-102,
bob@example.com,2025-01-16,11:15,2025-01-16,12:30,Bug fixes,TechStart,Mobile App,"BUG-204,urgent",Automatic Client & Project Creation
New clients and projects listed in the CSV will be created automatically if they don’t already exist.
Duplicate Detection
The import automatically skips duplicates:
- Activities with matching date, time, and description are skipped
- Prevents accidental double-imports
Team Member Import
Import activities for colleagues by including an email column in your CSV:
- The colleague must be a team member on the relevant client
- Each row’s email is matched to the corresponding user
- Activities are created under that user’s account
- They can see the imported activities in their reports
Toggl Import
Migrate your time tracking data from Toggl Track to Elastic Time.
Exporting from Toggl
- Log into Toggl Track
- Go to Settings (gear icon)
- Select Data Export
- Choose Time Entries
- Enter the year you want to export
- Click Export Time Entries
The exported CSV imports directly into Elastic Time. To export multiple years of data, repeat the process for each year.
AI Integration
Export data in formats optimized for AI assistants.
Markdown Export
- Go to Reports
- Filter your activities
- Click “AI (Markdown)”
The export organizes activities by:
- Project grouping
- Tag categorization
- Date ordering
Use this with AI assistants to:
- Generate executive summaries
- Create status reports
- Write time entry descriptions
HTML for AI Export
Similar to Markdown but with HTML structure:
- Go to Reports
- Click “AI (HTML)”
Some AI tools prefer HTML input for better structure recognition.
Best Practices
Consistent Tagging
For Jira integration to work well:
- Always use exact issue keys as tags (e.g.,
PROJ-123) - Be consistent with case (Jira keys are usually uppercase)
- One primary tag per activity for cleaner worklogs